From 81a69d956d03eb2709c64f1f077da273d4f8d0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 1 Nov 2016 17:35:18 +0000 Subject: [PATCH] docs: remove app dev manual and plugin writer's guide They have moved to gst-docs and will be maintained there in future. --- configure.ac | 3 - docs/Makefile.am | 4 +- docs/manual/.gitignore | 7 - docs/manual/Makefile.am | 41 - docs/manual/README | 61 - docs/manual/advanced-autoplugging.xml | 242 - docs/manual/advanced-buffering.xml | 450 - docs/manual/advanced-clocks.xml | 295 - docs/manual/advanced-dataaccess.xml | 1614 --- docs/manual/advanced-dparams.xml | 102 - docs/manual/advanced-interfaces.xml | 82 - docs/manual/advanced-metadata.xml | 196 - docs/manual/advanced-position.xml | 235 - docs/manual/advanced-threads.xml | 481 - docs/manual/appendix-checklist.xml | 204 - docs/manual/appendix-compiling.xml | 76 - docs/manual/appendix-integration.xml | 331 - docs/manual/appendix-licensing.xml | 101 - docs/manual/appendix-porting.xml | 316 - docs/manual/appendix-programs.xml | 342 - docs/manual/appendix-quotes.xml | 350 - docs/manual/base.css | 3 - docs/manual/basics-bins.xml | 185 - docs/manual/basics-bus.xml | 289 - docs/manual/basics-data.xml | 101 - docs/manual/basics-elements.xml | 567 - docs/manual/basics-helloworld.xml | 277 - docs/manual/basics-init.xml | 129 - docs/manual/basics-pads.xml | 686 -- docs/manual/basics-plugins.xml | 85 - docs/manual/bin-element-ghost.png | Bin 8532 -> 0 bytes docs/manual/bin-element-noghost.png | Bin 7934 -> 0 bytes docs/manual/bin-element.png | Bin 10835 -> 0 bytes docs/manual/clocks.png | Bin 65406 -> 0 bytes docs/manual/communication.png | Bin 31212 -> 0 bytes docs/manual/diagrams-clocks.svg | 1565 --- docs/manual/diagrams-general.svg | 14982 ------------------------ docs/manual/diagrams-pipelines.svg | 12768 -------------------- docs/manual/filter-element-multi.png | Bin 4383 -> 0 bytes docs/manual/filter-element.png | Bin 2718 -> 0 bytes docs/manual/gstreamer-overview.png | Bin 102876 -> 0 bytes docs/manual/hello-world.png | Bin 21240 -> 0 bytes docs/manual/highlevel-playback.xml | 617 - docs/manual/highlevel-xml.xml | 17 - docs/manual/images/.gitignore | 2 - docs/manual/intro-basics.xml | 159 - docs/manual/intro-gstreamer.xml | 99 - docs/manual/intro-motivation.xml | 300 - docs/manual/intro-preface.xml | 93 - docs/manual/linked-elements.png | Bin 7708 -> 0 bytes docs/manual/manual.xml | 269 - docs/manual/mime-world.png | Bin 48705 -> 0 bytes docs/manual/outline.txt | 92 - docs/manual/simple-player.png | Bin 53147 -> 0 bytes docs/manual/sink-element.png | Bin 3369 -> 0 bytes docs/manual/src-element.png | Bin 3611 -> 0 bytes docs/manual/state-diagram.svg | 233 - docs/manual/thread-buffering.png | Bin 23327 -> 0 bytes docs/manual/thread-synchronizing.png | Bin 43061 -> 0 bytes docs/manual/titlepage.xml | 69 - docs/pwg/.gitignore | 7 - docs/pwg/Makefile.am | 38 - docs/pwg/advanced-allocation.xml | 817 -- docs/pwg/advanced-clock.xml | 173 - docs/pwg/advanced-dparams.xml | 108 - docs/pwg/advanced-events.xml | 442 - docs/pwg/advanced-interfaces.xml | 237 - docs/pwg/advanced-negotiation.xml | 601 - docs/pwg/advanced-qos.xml | 283 - docs/pwg/advanced-request.xml | 290 - docs/pwg/advanced-scheduling.xml | 445 - docs/pwg/advanced-tagging.xml | 241 - docs/pwg/advanced-types.xml | 1431 --- docs/pwg/appendix-checklist.xml | 195 - docs/pwg/appendix-licensing.xml | 38 - docs/pwg/appendix-porting.xml | 196 - docs/pwg/appendix-python.xml | 0 docs/pwg/base.css | 0 docs/pwg/building-boiler.xml | 466 - docs/pwg/building-chainfn.xml | 158 - docs/pwg/building-eventfn.xml | 72 - docs/pwg/building-pads.xml | 146 - docs/pwg/building-props.xml | 169 - docs/pwg/building-queryfn.xml | 72 - docs/pwg/building-signals.xml | 16 - docs/pwg/building-state.xml | 184 - docs/pwg/building-testapp.xml | 216 - docs/pwg/intro-basics.xml | 395 - docs/pwg/intro-preface.xml | 296 - docs/pwg/other-base.xml | 310 - docs/pwg/other-manager.xml | 46 - docs/pwg/other-ntoone.xml | 155 - docs/pwg/other-oneton.xml | 45 - docs/pwg/other-sink.xml | 167 - docs/pwg/other-source.xml | 475 - docs/pwg/pwg.xml | 198 - docs/pwg/titlepage.xml | 98 - tests/examples/Makefile.am | 1 - tests/examples/manual/.gitignore | 50 - tests/examples/manual/Makefile.am | 136 - tests/examples/manual/extract.pl | 89 - 101 files changed, 2 insertions(+), 48620 deletions(-) delete mode 100644 docs/manual/.gitignore delete mode 100644 docs/manual/Makefile.am delete mode 100644 docs/manual/README delete mode 100644 docs/manual/advanced-autoplugging.xml delete mode 100644 docs/manual/advanced-buffering.xml delete mode 100644 docs/manual/advanced-clocks.xml delete mode 100644 docs/manual/advanced-dataaccess.xml delete mode 100644 docs/manual/advanced-dparams.xml delete mode 100644 docs/manual/advanced-interfaces.xml delete mode 100644 docs/manual/advanced-metadata.xml delete mode 100644 docs/manual/advanced-position.xml delete mode 100644 docs/manual/advanced-threads.xml delete mode 100644 docs/manual/appendix-checklist.xml delete mode 100644 docs/manual/appendix-compiling.xml delete mode 100644 docs/manual/appendix-integration.xml delete mode 100644 docs/manual/appendix-licensing.xml delete mode 100644 docs/manual/appendix-porting.xml delete mode 100644 docs/manual/appendix-programs.xml delete mode 100644 docs/manual/appendix-quotes.xml delete mode 100644 docs/manual/base.css delete mode 100644 docs/manual/basics-bins.xml delete mode 100644 docs/manual/basics-bus.xml delete mode 100644 docs/manual/basics-data.xml delete mode 100644 docs/manual/basics-elements.xml delete mode 100644 docs/manual/basics-helloworld.xml delete mode 100644 docs/manual/basics-init.xml delete mode 100644 docs/manual/basics-pads.xml delete mode 100644 docs/manual/basics-plugins.xml delete mode 100644 docs/manual/bin-element-ghost.png delete mode 100644 docs/manual/bin-element-noghost.png delete mode 100644 docs/manual/bin-element.png delete mode 100644 docs/manual/clocks.png delete mode 100644 docs/manual/communication.png delete mode 100644 docs/manual/diagrams-clocks.svg delete mode 100644 docs/manual/diagrams-general.svg delete mode 100644 docs/manual/diagrams-pipelines.svg delete mode 100644 docs/manual/filter-element-multi.png delete mode 100644 docs/manual/filter-element.png delete mode 100644 docs/manual/gstreamer-overview.png delete mode 100644 docs/manual/hello-world.png delete mode 100644 docs/manual/highlevel-playback.xml delete mode 100644 docs/manual/highlevel-xml.xml delete mode 100644 docs/manual/images/.gitignore delete mode 100644 docs/manual/intro-basics.xml delete mode 100644 docs/manual/intro-gstreamer.xml delete mode 100644 docs/manual/intro-motivation.xml delete mode 100644 docs/manual/intro-preface.xml delete mode 100644 docs/manual/linked-elements.png delete mode 100644 docs/manual/manual.xml delete mode 100644 docs/manual/mime-world.png delete mode 100644 docs/manual/outline.txt delete mode 100644 docs/manual/simple-player.png delete mode 100644 docs/manual/sink-element.png delete mode 100644 docs/manual/src-element.png delete mode 100644 docs/manual/state-diagram.svg delete mode 100644 docs/manual/thread-buffering.png delete mode 100644 docs/manual/thread-synchronizing.png delete mode 100644 docs/manual/titlepage.xml delete mode 100644 docs/pwg/.gitignore delete mode 100644 docs/pwg/Makefile.am delete mode 100644 docs/pwg/advanced-allocation.xml delete mode 100644 docs/pwg/advanced-clock.xml delete mode 100644 docs/pwg/advanced-dparams.xml delete mode 100644 docs/pwg/advanced-events.xml delete mode 100644 docs/pwg/advanced-interfaces.xml delete mode 100644 docs/pwg/advanced-negotiation.xml delete mode 100644 docs/pwg/advanced-qos.xml delete mode 100644 docs/pwg/advanced-request.xml delete mode 100644 docs/pwg/advanced-scheduling.xml delete mode 100644 docs/pwg/advanced-tagging.xml delete mode 100644 docs/pwg/advanced-types.xml delete mode 100644 docs/pwg/appendix-checklist.xml delete mode 100644 docs/pwg/appendix-licensing.xml delete mode 100644 docs/pwg/appendix-porting.xml delete mode 100644 docs/pwg/appendix-python.xml delete mode 100644 docs/pwg/base.css delete mode 100644 docs/pwg/building-boiler.xml delete mode 100644 docs/pwg/building-chainfn.xml delete mode 100644 docs/pwg/building-eventfn.xml delete mode 100644 docs/pwg/building-pads.xml delete mode 100644 docs/pwg/building-props.xml delete mode 100644 docs/pwg/building-queryfn.xml delete mode 100644 docs/pwg/building-signals.xml delete mode 100644 docs/pwg/building-state.xml delete mode 100644 docs/pwg/building-testapp.xml delete mode 100644 docs/pwg/intro-basics.xml delete mode 100644 docs/pwg/intro-preface.xml delete mode 100644 docs/pwg/other-base.xml delete mode 100644 docs/pwg/other-manager.xml delete mode 100644 docs/pwg/other-ntoone.xml delete mode 100644 docs/pwg/other-oneton.xml delete mode 100644 docs/pwg/other-sink.xml delete mode 100644 docs/pwg/other-source.xml delete mode 100644 docs/pwg/pwg.xml delete mode 100644 docs/pwg/titlepage.xml delete mode 100644 tests/examples/manual/.gitignore delete mode 100644 tests/examples/manual/Makefile.am delete mode 100755 tests/examples/manual/extract.pl diff --git a/configure.ac b/configure.ac index 544e584159..17f0d59192 100644 --- a/configure.ac +++ b/configure.ac @@ -1057,7 +1057,6 @@ tests/examples/adapter/Makefile tests/examples/controller/Makefile tests/examples/stepping/Makefile tests/examples/helloworld/Makefile -tests/examples/manual/Makefile tests/examples/memory/Makefile tests/examples/netclock/Makefile tests/examples/ptp/Makefile @@ -1073,8 +1072,6 @@ docs/gst/Makefile docs/gst/gstreamer.types docs/libs/Makefile docs/plugins/Makefile -docs/manual/Makefile -docs/pwg/Makefile docs/slides/Makefile docs/xsl/Makefile docs/version.entities diff --git a/docs/Makefile.am b/docs/Makefile.am index c39b7891b6..ac6432cc84 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,5 +1,5 @@ if ENABLE_DOCBOOK -SUBDIRS_DOCBOOK = faq manual pwg +SUBDIRS_DOCBOOK = faq else SUBDIRS_DOCBOOK = endif @@ -17,7 +17,7 @@ endif BUILT_SOURCES = version.entities SUBDIRS = design gst libs $(PLUGIN_DOCS_DIRS) $(SUBDIRS_DOCBOOK) -DIST_SUBDIRS = design gst libs plugins faq manual pwg slides xsl +DIST_SUBDIRS = design gst libs plugins faq slides xsl EXTRA_DIST = \ manuals.mak htmlinstall.mak \ diff --git a/docs/manual/.gitignore b/docs/manual/.gitignore deleted file mode 100644 index db6eb2ffb1..0000000000 --- a/docs/manual/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -.deps -build -html -*.pdf -*.ps diff --git a/docs/manual/Makefile.am b/docs/manual/Makefile.am deleted file mode 100644 index 65b6034441..0000000000 --- a/docs/manual/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -### this is the part you can customize if you need to - -# parallel builds don't work, probably due to temporary files -MAKEFLAGS = -j1 - -# base name of doc -DOC = manual -# formats defined for upload-doc.mak -FORMATS=html ps pdf - -# main xml file -MAIN = $(DOC).xml -# all xml sources -XML = $(notdir $(wildcard $(srcdir)/*.xml)) -# base style sheet -CSS = base.css - -# image sources -PNG_SRC = $(notdir $(wildcard $(srcdir)/*.png)) -FIG_SRC = $(notdir $(wildcard $(srcdir)/*.fig)) - -# extra sources to copy in build directory -EXTRA_SRC = - -### this is the generic bit and you shouldn't need to change this - -# get the generic docbuilding Makefile stuff -include $(srcdir)/../manuals.mak -# get the generic upload target -include $(top_srcdir)/common/upload-doc.mak - -### this is standard automake stuff - -# package up all the source -EXTRA_DIST = $(SRC) README - -# install documentation -manualdir = $(docdir)/$(DOC) -manual_DATA = $(PDF_DAT) $(PS_DAT) - -include $(srcdir)/../htmlinstall.mak diff --git a/docs/manual/README b/docs/manual/README deleted file mode 100644 index e2c4ea6af9..0000000000 --- a/docs/manual/README +++ /dev/null @@ -1,61 +0,0 @@ -Current requirements for building the docs : --------------------------------------------- - -libxslt >= 1.0.6 -libxml2 >= 2.4.12 - - -These are not included with RH72. They are in debian. GDE has good rpms. - -To build pdf's from xslt stuff, you need xmltex and (on redhat) -passivetex. They are not known to have been built on either redhat or -debian yet though. - -Wingo's new comments on the doc building : ------------------------------------------- -* Well he should add them soon here since he overhauled it. And did a good - job on it too ;) - -Thomas's new comments on the doc building : -------------------------------------------- -* originally the manual was written with DocBook 3.0 in mind, which - supported the graphic tag. That is now deprecated, so I changed it to - the new mediaobject tag set. - -* eps files in images/ should be generated from the makefile. You need to - have fig2dev installed for that. - -Ensonic's comments on the doc build system : --------------------------------------------- -In case you like to share files between the manual and the pwg - it's -not trivial. -Before anything is done, the build-system copies all xml files into the build -subdir and this breaks including shared docs via entities. - -The examples should be updated in the xml. We run a perlscript in -tests/examples/manual that extracts them. - -Wtay's original comments : --------------------------- - -For now use: - - db2html gstreamer-manual - -(On debian, db2html is in the cygnus-stylesheets package) - -You will need the png support for docbook (see GNOME documentation project) - -convert the fig images to png with: - - fig2dev -L png -s 16 fig/.fig images/.png - -Put a link in the gstreamer-manual directory with - - ln -s ../images gstreamer-manual/images - -point your browser to gstreamer-manual/gstreamer.html - -Fix typing errors and correct bad english. -Let me know about the stuff that needs some more explanation. -Let me know about the structure of the document. diff --git a/docs/manual/advanced-autoplugging.xml b/docs/manual/advanced-autoplugging.xml deleted file mode 100644 index 5f7a0e0e67..0000000000 --- a/docs/manual/advanced-autoplugging.xml +++ /dev/null @@ -1,242 +0,0 @@ - - Autoplugging - - In , you've learned to build a - simple media player for Ogg/Vorbis files. By using alternative elements, - you are able to build media players for other media types, such as - Ogg/Speex, MP3 or even video formats. However, you would rather want - to build an application that can automatically detect the media type - of a stream and automatically generate the best possible pipeline - by looking at all available elements in a system. This process is called - autoplugging, and &GStreamer; contains high-quality autopluggers. If - you're looking for an autoplugger, don't read any further and go to - . This chapter will explain the - concept of autoplugging and typefinding. It will - explain what systems &GStreamer; includes to dynamically detect the - type of a media stream, and how to generate a pipeline of decoder - elements to playback this media. The same principles can also be used - for transcoding. Because of the full dynamicity of this concept, - &GStreamer; can be automatically extended to support new media types - without needing any adaptations to its autopluggers. - - - We will first introduce the concept of Media types as a dynamic and - extendible way of identifying media streams. After that, we will introduce - the concept of typefinding to find the type of a media stream. Lastly, - we will explain how autoplugging and the &GStreamer; registry can be - used to setup a pipeline that will convert media from one mediatype to - another, for example for media decoding. - - - - Media types as a way to identify streams - - We have previously introduced the concept of capabilities as a way - for elements (or, rather, pads) to agree on a media type when - streaming data from one element to the next (see ). We have explained that a capability is - a combination of a media type and a set of properties. For most - container formats (those are the files that you will find on your - hard disk; Ogg, for example, is a container format), no properties - are needed to describe the stream. Only a media type is needed. A - full list of media types and accompanying properties can be found - in the - Plugin Writer's Guide. - - - An element must associate a media type to its source and sink pads - when it is loaded into the system. &GStreamer; knows about the - different elements and what type of data they expect and emit through - the &GStreamer; registry. This allows for very dynamic and extensible - element creation as we will see. - - - - In , we've learned to build a - music player for Ogg/Vorbis files. Let's look at the media types - associated with each pad in this pipeline. shows what media type belongs to each - pad in this pipeline. - - -
- The Hello world pipeline with media types - - - - - -
- - - Now that we have an idea how &GStreamer; identifies known media - streams, we can look at methods &GStreamer; uses to setup pipelines - for media handling and for media type detection. - -
- - - Media stream type detection - - Usually, when loading a media stream, the type of the stream is not - known. This means that before we can choose a pipeline to decode the - stream, we first need to detect the stream type. &GStreamer; uses the - concept of typefinding for this. Typefinding is a normal part of a - pipeline, it will read data for as long as the type of a stream is - unknown. During this period, it will provide data to all plugins - that implement a typefinder. When one of the typefinders recognizes - the stream, the typefind element will emit a signal and act as a - passthrough module from that point on. If no type was found, it will - emit an error and further media processing will stop. - - - Once the typefind element has found a type, the application can - use this to plug together a pipeline to decode the media stream. - This will be discussed in the next section. - - - Plugins in &GStreamer; can, as mentioned before, implement typefinder - functionality. A plugin implementing this functionality will submit - a media type, optionally a set of file extensions commonly used for this - media type, and a typefind function. Once this typefind function inside - the plugin is called, the plugin will see if the data in this media - stream matches a specific pattern that marks the media type identified - by that media type. If it does, it will notify the typefind element of - this fact, telling which mediatype was recognized and how certain we - are that this stream is indeed that mediatype. Once this run has been - completed for all plugins implementing a typefind functionality, the - typefind element will tell the application what kind of media stream - it thinks to have recognized. - - - The following code should explain how to use the typefind element. - It will print the detected media type, or tell that the media type - was not found. The next section will introduce more useful behaviours, - such as plugging together a decoding pipeline. - - -#include <gst/gst.h> - -[.. my_bus_callback goes here ..] - -static gboolean -idle_exit_loop (gpointer data) -{ - g_main_loop_quit ((GMainLoop *) data); - - /* once */ - return FALSE; -} - -static void -cb_typefound (GstElement *typefind, - guint probability, - GstCaps *caps, - gpointer data) -{ - GMainLoop *loop = data; - gchar *type; - - type = gst_caps_to_string (caps); - g_print ("Media type %s found, probability %d%%\n", type, probability); - g_free (type); - - /* since we connect to a signal in the pipeline thread context, we need - * to set an idle handler to exit the main loop in the mainloop context. - * Normally, your app should not need to worry about such things. */ - g_idle_add (idle_exit_loop, loop); -} - -gint -main (gint argc, - gchar *argv[]) -{ - GMainLoop *loop; - GstElement *pipeline, *filesrc, *typefind, *fakesink; - GstBus *bus; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* check args */ - if (argc != 2) { - g_print ("Usage: %s <filename>\n", argv[0]); - return -1; - } - - /* create a new pipeline to hold the elements */ - pipeline = gst_pipeline_new ("pipe"); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, my_bus_callback, NULL); - gst_object_unref (bus); - - /* create file source and typefind element */ - filesrc = gst_element_factory_make ("filesrc", "source"); - g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); - typefind = gst_element_factory_make ("typefind", "typefinder"); - g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), loop); - fakesink = gst_element_factory_make ("fakesink", "sink"); - - /* setup */ - gst_bin_add_many (GST_BIN (pipeline), filesrc, typefind, fakesink, NULL); - gst_element_link_many (filesrc, typefind, fakesink, NULL); - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); - g_main_loop_run (loop); - - /* unset */ - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - - return 0; -} - - - Once a media type has been detected, you can plug an element (e.g. a - demuxer or decoder) to the source pad of the typefind element, and - decoding of the media stream will start right after. - - - - - Dynamically autoplugging a pipeline - - See for using the high - level object that you can use to dynamically construct pipelines. - - -
diff --git a/docs/manual/advanced-buffering.xml b/docs/manual/advanced-buffering.xml deleted file mode 100644 index 7facd85433..0000000000 --- a/docs/manual/advanced-buffering.xml +++ /dev/null @@ -1,450 +0,0 @@ - - Buffering - - The purpose of buffering is to accumulate enough data in a pipeline so that - playback can occur smoothly and without interruptions. It is typically done - when reading from a (slow) and non-live network source but can also be - used for live sources. - - - &GStreamer; provides support for the following use cases: - - - - Buffering up to a specific amount of data, in memory, before starting - playback so that network fluctuations are minimized. - See . - - - - - Download of the network file to a local disk with fast seeking in the - downloaded data. This is similar to the quicktime/youtube players. - See . - - - - - Caching of (semi)-live streams to a local, on disk, ringbuffer with - seeking in the cached area. This is similar to tivo-like timeshifting. - See . - - - - - - &GStreamer; can provide the application with progress reports about the - current buffering state as well as let the application decide on how - to buffer and when the buffering stops. - - - In the most simple case, the application has to listen for BUFFERING - messages on the bus. If the percent indicator inside the BUFFERING message - is smaller than 100, the pipeline is buffering. When a message is - received with 100 percent, buffering is complete. In the buffering state, - the application should keep the pipeline in the PAUSED state. When buffering - completes, it can put the pipeline (back) in the PLAYING state. - - - What follows is an example of how the message handler could deal with - the BUFFERING messages. We will see more advanced methods in - . - - - - - - - Stream buffering - - +---------+ +---------+ +-------+ - | httpsrc | | buffer | | demux | - | src - sink src - sink .... - +---------+ +---------+ +-------+ - - - In this case we are reading from a slow network source into a buffer - element (such as queue2). - - - The buffer element has a low and high watermark expressed in bytes. The - buffer uses the watermarks as follows: - - - - - The buffer element will post BUFFERING messages until the high - watermark is hit. This instructs the application to keep the pipeline - PAUSED, which will eventually block the srcpad from pushing while - data is prerolled in the sinks. - - - - - When the high watermark is hit, a BUFFERING message with 100% will be - posted, which instructs the application to continue playback. - - - - - When during playback, the low watermark is hit, the queue will start - posting BUFFERING messages again, making the application PAUSE the - pipeline again until the high watermark is hit again. This is called - the rebuffering stage. - - - - - During playback, the queue level will fluctuate between the high and - the low watermark as a way to compensate for network irregularities. - - - - - This buffering method is usable when the demuxer operates in push mode. - Seeking in the stream requires the seek to happen in the network source. - It is mostly desirable when the total duration of the file is not known, - such as in live streaming or when efficient seeking is not - possible/required. - - - The problem is configuring a good low and high watermark. Here are some - ideas: - - - - - It is possible to measure the network bandwidth and configure the - low/high watermarks in such a way that buffering takes a fixed - amount of time. - - - The queue2 element in &GStreamer; core has the max-size-time property - that, together with the use-rate-estimate property, does exactly - that. Also the playbin buffer-duration property uses the rate estimate - to scale the amount of data that is buffered. - - - - - Based on the codec bitrate, it is also possible to set the watermarks - in such a way that a fixed amount of data is buffered before playback - starts. Normally, the buffering element doesn't know about the - bitrate of the stream but it can get this with a query. - - - - - Start with a fixed amount of bytes, measure the time between - rebuffering and increase the queue size until the time between - rebuffering is within the application's chosen limits. - - - - - The buffering element can be inserted anywhere in the pipeline. You could, - for example, insert the buffering element before a decoder. This would - make it possible to set the low/high watermarks based on time. - - - The buffering flag on playbin, performs buffering on the parsed data. - Another advantage of doing the buffering at a later stage is that you can - let the demuxer operate in pull mode. When reading data from a slow - network drive (with filesrc) this can be an interesting way to buffer. - - - - - Download buffering - - +---------+ +---------+ +-------+ - | httpsrc | | buffer | | demux | - | src - sink src - sink .... - +---------+ +----|----+ +-------+ - V - file - - - If we know the server is streaming a fixed length file to the client, - the application can choose to download the entire file on disk. The - buffer element will provide a push or pull based srcpad to the demuxer - to navigate in the downloaded file. - - - This mode is only suitable when the client can determine the length of - the file on the server. - - - In this case, buffering messages will be emitted as usual when the - requested range is not within the downloaded area + buffersize. The - buffering message will also contain an indication that incremental - download is being performed. This flag can be used to let the application - control the buffering in a more intelligent way, using the BUFFERING - query, for example. See . - - - - - Timeshift buffering - - +---------+ +---------+ +-------+ - | httpsrc | | buffer | | demux | - | src - sink src - sink .... - +---------+ +----|----+ +-------+ - V - file-ringbuffer - - - In this mode, a fixed size ringbuffer is kept to download the server - content. This allows for seeking in the buffered data. Depending on the - size of the ringbuffer one can seek further back in time. - - - This mode is suitable for all live streams. As with the incremental - download mode, buffering messages are emitted along with an indication - that timeshifting download is in progress. - - - - - Live buffering - - In live pipelines we usually introduce some fixed latency between the - capture and the playback elements. This latency can be introduced by - a queue (such as a jitterbuffer) or by other means (in the audiosink). - - - Buffering messages can be emitted in those live pipelines as well and - serve as an indication to the user of the latency buffering. The - application usually does not react to these buffering messages with a - state change. - - - - - Buffering strategies - - What follows are some ideas for implementing different buffering - strategies based on the buffering messages and buffering query. - - - - No-rebuffer strategy - - We would like to buffer enough data in the pipeline so that playback - continues without interruptions. What we need to know to implement - this is know the total remaining playback time in the file and the - total remaining download time. If the buffering time is less than the - playback time, we can start playback without interruptions. - - - We have all this information available with the DURATION, POSITION and - BUFFERING queries. We need to periodically execute the buffering query - to get the current buffering status. We also need to have a large - enough buffer to hold the complete file, worst case. It is best to - use this buffering strategy with download buffering (see - ). - - - This is what the code would look like: - - - - - -GstState target_state; -static gboolean is_live; -static gboolean is_buffering; - -static gboolean -buffer_timeout (gpointer data) -{ - GstElement *pipeline = data; - GstQuery *query; - gboolean busy; - gint percent; - gint64 estimated_total; - gint64 position, duration; - guint64 play_left; - - query = gst_query_new_buffering (GST_FORMAT_TIME); - - if (!gst_element_query (pipeline, query)) - return TRUE; - - gst_query_parse_buffering_percent (query, &busy, &percent); - gst_query_parse_buffering_range (query, NULL, NULL, NULL, &estimated_total); - - if (estimated_total == -1) - estimated_total = 0; - - /* calculate the remaining playback time */ - if (!gst_element_query_position (pipeline, GST_FORMAT_TIME, &position)) - position = -1; - if (!gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration)) - duration = -1; - - if (duration != -1 && position != -1) - play_left = GST_TIME_AS_MSECONDS (duration - position); - else - play_left = 0; - - g_message ("play_left %" G_GUINT64_FORMAT", estimated_total %" G_GUINT64_FORMAT - ", percent %d", play_left, estimated_total, percent); - - /* we are buffering or the estimated download time is bigger than the - * remaining playback time. We keep buffering. */ - is_buffering = (busy || estimated_total * 1.1 > play_left); - - if (!is_buffering) - gst_element_set_state (pipeline, target_state); - - return is_buffering; -} - -static void -on_message_buffering (GstBus *bus, GstMessage *message, gpointer user_data) -{ - GstElement *pipeline = user_data; - gint percent; - - /* no state management needed for live pipelines */ - if (is_live) - return; - - gst_message_parse_buffering (message, &percent); - - if (percent < 100) { - /* buffering busy */ - if (!is_buffering) { - is_buffering = TRUE; - if (target_state == GST_STATE_PLAYING) { - /* we were not buffering but PLAYING, PAUSE the pipeline. */ - gst_element_set_state (pipeline, GST_STATE_PAUSED); - } - } - } -} - -static void -on_message_async_done (GstBus *bus, GstMessage *message, gpointer user_data) -{ - GstElement *pipeline = user_data; - - if (!is_buffering) - gst_element_set_state (pipeline, target_state); - else - g_timeout_add (500, buffer_timeout, pipeline); -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstElement *pipeline; - GMainLoop *loop; - GstBus *bus; - GstStateChangeReturn ret; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* make sure we have a URI */ - if (argc != 2) { - g_print ("Usage: %s <URI>\n", argv[0]); - return -1; - } - - /* set up */ - pipeline = gst_element_factory_make ("playbin", "pipeline"); - g_object_set (G_OBJECT (pipeline), "uri", argv[1], NULL); - g_object_set (G_OBJECT (pipeline), "flags", 0x697 , NULL); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_signal_watch (bus); - - g_signal_connect (bus, "message::buffering", - (GCallback) on_message_buffering, pipeline); - g_signal_connect (bus, "message::async-done", - (GCallback) on_message_async_done, pipeline); - gst_object_unref (bus); - - is_buffering = FALSE; - target_state = GST_STATE_PLAYING; - ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); - - switch (ret) { - case GST_STATE_CHANGE_SUCCESS: - is_live = FALSE; - break; - - case GST_STATE_CHANGE_FAILURE: - g_warning ("failed to PAUSE"); - return -1; - - case GST_STATE_CHANGE_NO_PREROLL: - is_live = TRUE; - break; - - default: - break; - } - - /* now run */ - g_main_loop_run (loop); - - /* also clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - g_main_loop_unref (loop); - - return 0; -} -]]> - - - - See how we set the pipeline to the PAUSED state first. We will receive - buffering messages during the preroll state when buffering is needed. - When we are prerolled (on_message_async_done) we see if buffering is - going on, if not, we start playback. If buffering was going on, we start - a timeout to poll the buffering state. If the estimated time to download - is less than the remaining playback time, we start playback. - - - - diff --git a/docs/manual/advanced-clocks.xml b/docs/manual/advanced-clocks.xml deleted file mode 100644 index 41306272e0..0000000000 --- a/docs/manual/advanced-clocks.xml +++ /dev/null @@ -1,295 +0,0 @@ - - Clocks and synchronization in &GStreamer; - - - When playing complex media, each sound and video sample must be played in a - specific order at a specific time. For this purpose, GStreamer provides a - synchronization mechanism. - - - &GStreamer; provides support for the following use cases: - - - - Non-live sources with access faster than playback rate. This is - the case where one is reading media from a file and playing it - back in a synchronized fashion. In this case, multiple streams need - to be synchronized, like audio, video and subtitles. - - - - - Capture and synchronized muxing/mixing of media from multiple live - sources. This is a typical use case where you record audio and - video from a microphone/camera and mux it into a file for - storage. - - - - - Streaming from (slow) network streams with buffering. This is the - typical web streaming case where you access content from a streaming - server with http. - - - - - Capture from live source and and playback to live source with - configurable latency. This is used when, for example, capture from - a camera, apply an effect and display the result. It is also used - when streaming low latency content over a network with UDP. - - - - - Simultaneous live capture and playback from prerecorded content. - This is used in audio recording cases where you play a previously - recorded audio and record new samples, the purpose is to have the - new audio perfectly in sync with the previously recorded data. - - - - - - &GStreamer; uses a GstClock object, buffer - timestamps and a SEGMENT event to synchronize streams in a pipeline - as we will see in the next sections. - - - - Clock running-time - - In a typical computer, there are many sources that can be used as a - time source, e.g., the system time, soundcards, CPU performance - counters, ... For this reason, there are many - GstClock implementations available in &GStreamer;. - The clock time doesn't always start from 0 or from some known value. - Some clocks start counting from some known start date, other clocks start - counting since last reboot, etc... - - - A GstClock returns the - absolute-time - according to that clock with gst_clock_get_time (). - The absolute-time (or clock time) of a clock is monotonically increasing. - From the absolute-time is a running-time - calculated, which is simply the difference between a previous snapshot - of the absolute-time called the base-time. - So: - - - running-time = absolute-time - base-time - - - A &GStreamer; GstPipeline object maintains a - GstClock object and a base-time when it goes - to the PLAYING state. The pipeline gives a handle to the selected - GstClock to each element in the pipeline along - with selected base-time. The pipeline will select a base-time in such - a way that the running-time reflects the total time spent in the - PLAYING state. As a result, when the pipeline is PAUSED, the - running-time stands still. - - - Because all objects in the pipeline have the same clock and base-time, - they can thus all calculate the running-time according to the pipeline - clock. - - - - - Buffer running-time - - To calculate a buffer running-time, we need a buffer timestamp and - the SEGMENT event that preceeded the buffer. First we can convert - the SEGMENT event into a GstSegment object - and then we can use the - gst_segment_to_running_time () function to - perform the calculation of the buffer running-time. - - - Synchronization is now a matter of making sure that a buffer with a - certain running-time is played when the clock reaches the same - running-time. Usually this task is done by sink elements. Sink also - have to take into account the latency configured in the pipeline and - add this to the buffer running-time before synchronizing to the - pipeline clock. - - - Non-live sources timestamp buffers with a running-time starting - from 0. After a flushing seek, they will produce buffers again - from a running-time of 0. - - - Live sources need to timestamp buffers with a running-time matching - the pipeline running-time when the first byte of the buffer was - captured. - - - - - Buffer stream-time - - The buffer stream-time, also known as the position in the stream, - is calculated from the buffer timestamps and the preceding SEGMENT - event. It represents the time inside the media as a value between - 0 and the total duration of the media. - - - The stream-time is used in: - - - - Report the current position in the stream with the POSITION - query. - - - - - The position used in the seek events and queries. - - - - - The position used to synchronize controlled values. - - - - - - The stream-time is never used to synchronize streams, this is only - done with the running-time. - - - - - Time overview - - Here is an overview of the various timelines used in &GStreamer;. - - - The image below represents the different times in the pipeline when - playing a 100ms sample and repeating the part between 50ms and - 100ms. - - -
- &GStreamer; clock and various times - - - - - -
- - - You can see how the running-time of a buffer always increments - monotonically along with the clock-time. Buffers are played when their - running-time is equal to the clock-time - base-time. The stream-time - represents the position in the stream and jumps backwards when - repeating. - -
- - - Clock providers - - A clock provider is an element in the pipeline that can provide - a GstClock object. The clock object needs to - report an absolute-time that is monotonically increasing when the - element is in the PLAYING state. It is allowed to pause the clock - while the element is PAUSED. - - - Clock providers exist because they play back media at some rate, and - this rate is not necessarily the same as the system clock rate. For - example, a soundcard may playback at 44,1 kHz, but that doesn't mean - that after exactly 1 second according - to the system clock, the soundcard has played back 44.100 - samples. This is only true by approximation. In fact, the audio - device has an internal clock based on the number of samples played - that we can expose. - - - If an element with an internal clock needs to synchronize, it needs - to estimate when a time according to the pipeline clock will take - place according to the internal clock. To estimate this, it needs - to slave its clock to the pipeline clock. - - - If the pipeline clock is exactly the internal clock of an element, - the element can skip the slaving step and directly use the pipeline - clock to schedule playback. This can be both faster and more - accurate. - Therefore, generally, elements with an internal clock like audio - input or output devices will be a clock provider for the pipeline. - - - When the pipeline goes to the PLAYING state, it will go over all - elements in the pipeline from sink to source and ask each element - if they can provide a clock. The last element that can provide a - clock will be used as the clock provider in the pipeline. - This algorithm prefers a clock from an audio sink in a typical - playback pipeline and a clock from source elements in a typical - capture pipeline. - - - There exist some bus messages to let you know about the clock and - clock providers in the pipeline. You can see what clock is selected - in the pipeline by looking at the NEW_CLOCK message on the bus. - When a clock provider is removed from the pipeline, a CLOCK_LOST - message is posted and the application should go to PAUSED and back - to PLAYING to select a new clock. - - - - - Latency - - The latency is the time it takes for a sample captured at timestamp X - to reach the sink. This time is measured against the clock in the - pipeline. For pipelines where the only elements that synchronize against - the clock are the sinks, the latency is always 0 since no other element - is delaying the buffer. - - - For pipelines with live sources, a latency is introduced, mostly because - of the way a live source works. Consider an audio source, it will start - capturing the first sample at time 0. If the source pushes buffers with - 44100 samples at a time at 44100Hz it will have collected the buffer at - second 1. Since the timestamp of the buffer is 0 and the time of the - clock is now >= 1 second, the sink will drop this buffer because it is - too late. Without any latency compensation in the sink, all buffers will - be dropped. - - - - Latency compensation - - Before the pipeline goes to the PLAYING state, it will, in addition to - selecting a clock and calculating a base-time, calculate the latency - in the pipeline. It does this by doing a LATENCY query on all the sinks - in the pipeline. The pipeline then selects the maximum latency in the - pipeline and configures this with a LATENCY event. - - - All sink elements will delay playback by the value in the LATENCY event. - Since all sinks delay with the same amount of time, they will be - relative in sync. - - - - - Dynamic Latency - - Adding/removing elements to/from a pipeline or changing element - properties can change the latency in a pipeline. An element can - request a latency change in the pipeline by posting a LATENCY - message on the bus. The application can then decide to query and - redistribute a new latency or not. Changing the latency in a - pipeline might cause visual or audible glitches and should - therefore only be done by the application when it is allowed. - - - -
diff --git a/docs/manual/advanced-dataaccess.xml b/docs/manual/advanced-dataaccess.xml deleted file mode 100644 index 10f5d6befa..0000000000 --- a/docs/manual/advanced-dataaccess.xml +++ /dev/null @@ -1,1614 +0,0 @@ - - Pipeline manipulation - - This chapter will discuss how you can manipulate your pipeline in several - ways from your application on. Parts of this chapter are very - lowlevel, so be assured that you'll need some programming knowledge - and a good understanding of &GStreamer; before you start reading this. - - - Topics that will be discussed here include how you can insert data into - a pipeline from your application, how to read data from a pipeline, - how to manipulate the pipeline's speed, length, starting point and how - to listen to a pipeline's data processing. - - - - Using probes - - Probing is best envisioned as a pad listener. Technically, a probe is - nothing more than a callback that can be attached to a pad. - You can attach a probe using gst_pad_add_probe (). - Similarly, one can use the - gst_pad_remove_probe () - to remove the callback again. The probe notifies you of any activity - that happens on the pad, like buffers, events and queries. You can - define what kind of notifications you are interested in when you - add the probe. - - - The probe can notify you of the following activity on pads: - - - - - A buffer is pushed or pulled. You want to specify the - GST_PAD_PROBE_TYPE_BUFFER when registering the probe. Because the - pad can be scheduled in different ways, it is possible to also - specify in what scheduling mode you are interested with the - optional GST_PAD_PROBE_TYPE_PUSH and GST_PAD_PROBE_TYPE_PULL - flags. - - - You can use this probe to inspect, modify or drop the buffer. - See . - - - - - A bufferlist is pushed. Use the GST_PAD_PROBE_TYPE_BUFFER_LIST - when registering the probe. - - - - - An event travels over a pad. Use the GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM - and GST_PAD_PROBE_TYPE_EVENT_UPSTREAM flags to select downstream - and upstream events. There is also a convenience - GST_PAD_PROBE_TYPE_EVENT_BOTH to be notified of events going both - upstream and downstream. By default, flush events do not cause - a notification. You need to explicitly enable GST_PAD_PROBE_TYPE_EVENT_FLUSH - to receive callbacks from flushing events. Events are always - only notified in push mode. - - - You can use this probe to inspect, modify or drop the event. - - - - - A query travels over a pad. Use the GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM - and GST_PAD_PROBE_TYPE_QUERY_UPSTREAM flags to select downstream - and upstream queries. The convenience GST_PAD_PROBE_TYPE_QUERY_BOTH - can also be used to select both directions. Query probes will be - notified twice, once when the query travels upstream/downstream and - once when the query result is returned. You can select in what stage - the callback will be called with the GST_PAD_PROBE_TYPE_PUSH and - GST_PAD_PROBE_TYPE_PULL, respectively when the query is performed - and when the query result is returned. - - - You can use this probe to inspect or modify the query. You can also - answer the query in the probe callback by placing the result value - in the query and by returning GST_PAD_PROBE_DROP from the - callback. - - - - - In addition to notifying you of dataflow, you can also ask the - probe to block the dataflow when the callback returns. This is - called a blocking probe and is activated by specifying the - GST_PAD_PROBE_TYPE_BLOCK flag. You can use this flag with the - other flags to only block dataflow on selected activity. A pad - becomes unblocked again if you remove the probe or when you return - GST_PAD_PROBE_REMOVE from the callback. You can let only the - currently blocked item pass by returning GST_PAD_PROBE_PASS - from the callback, it will block again on the next item. - - - Blocking probes are used to temporarily block pads because they - are unlinked or because you are going to unlink them. If the - dataflow is not blocked, the pipeline would go into an error - state if data is pushed on an unlinked pad. We will se how - to use blocking probes to partially preroll a pipeline. - See also . - - - - - Be notified when no activity is happening on a pad. You install - this probe with the GST_PAD_PROBE_TYPE_IDLE flag. You can specify - GST_PAD_PROBE_TYPE_PUSH and/or GST_PAD_PROBE_TYPE_PULL to - only be notified depending on the pad scheduling mode. - The IDLE probe is also a blocking probe in that it will not let - any data pass on the pad for as long as the IDLE probe is - installed. - - - You can use idle probes to dynamically relink a pad. We will see - how to use idle probes to replace an element in the pipeline. - See also . - - - - - - Data probes - - Data probes allow you to be notified when there is data passing - on a pad. When adding the probe, specify the GST_PAD_PROBE_TYPE_BUFFER - and/or GST_PAD_PROBE_TYPE_BUFFER_LIST. - - - Data probes run in pipeline streaming thread context, so callbacks - should try to not block and generally not do any weird stuff, since - this could have a negative impact on pipeline performance or, in case - of bugs, cause deadlocks or crashes. More precisely, one should usually - not call any GUI-related functions from within a probe callback, nor try - to change the state of the pipeline. An application may post custom - messages on the pipeline's bus though to communicate with the main - application thread and have it do things like stop the pipeline. - - - In any case, most common buffer operations - that elements can do in _chain () functions, can - be done in probe callbacks as well. The example below gives a short - impression on how to use them. - - - - - -static GstPadProbeReturn -cb_have_data (GstPad *pad, - GstPadProbeInfo *info, - gpointer user_data) -{ - gint x, y; - GstMapInfo map; - guint16 *ptr, t; - GstBuffer *buffer; - - buffer = GST_PAD_PROBE_INFO_BUFFER (info); - - buffer = gst_buffer_make_writable (buffer); - - /* Making a buffer writable can fail (for example if it - * cannot be copied and is used more than once) - */ - if (buffer == NULL) - return GST_PAD_PROBE_OK; - - /* Mapping a buffer can fail (non-writable) */ - if (gst_buffer_map (buffer, &map, GST_MAP_WRITE)) { - ptr = (guint16 *) map.data; - /* invert data */ - for (y = 0; y < 288; y++) { - for (x = 0; x < 384 / 2; x++) { - t = ptr[384 - 1 - x]; - ptr[384 - 1 - x] = ptr[x]; - ptr[x] = t; - } - ptr += 384; - } - gst_buffer_unmap (buffer, &map); - } - - GST_PAD_PROBE_INFO_DATA (info) = buffer; - - return GST_PAD_PROBE_OK; -} - -gint -main (gint argc, - gchar *argv[]) -{ - GMainLoop *loop; - GstElement *pipeline, *src, *sink, *filter, *csp; - GstCaps *filtercaps; - GstPad *pad; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* build */ - pipeline = gst_pipeline_new ("my-pipeline"); - src = gst_element_factory_make ("videotestsrc", "src"); - if (src == NULL) - g_error ("Could not create 'videotestsrc' element"); - - filter = gst_element_factory_make ("capsfilter", "filter"); - g_assert (filter != NULL); /* should always exist */ - - csp = gst_element_factory_make ("videoconvert", "csp"); - if (csp == NULL) - g_error ("Could not create 'videoconvert' element"); - - sink = gst_element_factory_make ("xvimagesink", "sink"); - if (sink == NULL) { - sink = gst_element_factory_make ("ximagesink", "sink"); - if (sink == NULL) - g_error ("Could not create neither 'xvimagesink' nor 'ximagesink' element"); - } - - gst_bin_add_many (GST_BIN (pipeline), src, filter, csp, sink, NULL); - gst_element_link_many (src, filter, csp, sink, NULL); - filtercaps = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, "RGB16", - "width", G_TYPE_INT, 384, - "height", G_TYPE_INT, 288, - "framerate", GST_TYPE_FRACTION, 25, 1, - NULL); - g_object_set (G_OBJECT (filter), "caps", filtercaps, NULL); - gst_caps_unref (filtercaps); - - pad = gst_element_get_static_pad (src, "src"); - gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, - (GstPadProbeCallback) cb_have_data, NULL, NULL); - gst_object_unref (pad); - - /* run */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - /* wait until it's up and running or failed */ - if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) { - g_error ("Failed to go into PLAYING state"); - } - - g_print ("Running ...\n"); - g_main_loop_run (loop); - - /* exit */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - - return 0; -} -]]> - - - - Compare that output with the output of gst-launch-1.0 - videotestsrc ! xvimagesink, just so you know what you're - looking for. - - - Strictly speaking, a pad probe callback is only allowed to modify the - buffer content if the buffer is writable. Whether this is the case or - not depends a lot on the pipeline and the elements involved. Often - enough, this is the case, but sometimes it is not, and if it is not - then unexpected modification of the data or metadata can introduce - bugs that are very hard to debug and track down. You can check if a - buffer is writable with gst_buffer_is_writable (). - Since you can pass back a different buffer than the one passed in, - it is a good idea to make the buffer writable in the callback function - with gst_buffer_make_writable (). - - - Pad probes are suited best for looking at data as it passes through - the pipeline. If you need to modify data, you should better write your - own GStreamer element. Base classes like GstAudioFilter, GstVideoFilter or - GstBaseTransform make this fairly easy. - - - If you just want to inspect buffers as they pass through the pipeline, - you don't even need to set up pad probes. You could also just insert - an identity element into the pipeline and connect to its "handoff" - signal. The identity element also provides a few useful debugging tools - like the "dump" property or the "last-message" property (the latter is - enabled by passing the '-v' switch to gst-launch and by setting the - silent property on the identity to FALSE). - - - - - Play a region of a media file - - In this example we will show you how to play back a region of - a media file. The goal is to only play the part of a file - from 2 seconds to 5 seconds and then EOS. - - - In a first step we will set a uridecodebin element to the PAUSED - state and make sure that we block all the source pads that are - created. When all the source pads are blocked, we have data on - all source pads and we say that the uridecodebin is prerolled. - - - In a prerolled pipeline we can ask for the duration of the media - and we can also perform seeks. We are interested in performing a - seek operation on the pipeline to select the range of media - that we are interested in. - - - After we configure the region we are interested in, we can link - the sink element, unblock the source pads and set the pipeline to - the playing state. You will see that exactly the requested - region is played by the sink before it goes to EOS. - - - What follows is an example application that loosly follows this - algorithm. - - - - - -static GMainLoop *loop; -static volatile gint counter; -static GstBus *bus; -static gboolean prerolled = FALSE; -static GstPad *sinkpad; - -static void -dec_counter (GstElement * pipeline) -{ - if (prerolled) - return; - - if (g_atomic_int_dec_and_test (&counter)) { - /* all probes blocked and no-more-pads signaled, post - * message on the bus. */ - prerolled = TRUE; - - gst_bus_post (bus, gst_message_new_application ( - GST_OBJECT_CAST (pipeline), - gst_structure_new_empty ("ExPrerolled"))); - } -} - -/* called when a source pad of uridecodebin is blocked */ -static GstPadProbeReturn -cb_blocked (GstPad *pad, - GstPadProbeInfo *info, - gpointer user_data) -{ - GstElement *pipeline = GST_ELEMENT (user_data); - - if (prerolled) - return GST_PAD_PROBE_REMOVE; - - dec_counter (pipeline); - - return GST_PAD_PROBE_OK; -} - -/* called when uridecodebin has a new pad */ -static void -cb_pad_added (GstElement *element, - GstPad *pad, - gpointer user_data) -{ - GstElement *pipeline = GST_ELEMENT (user_data); - - if (prerolled) - return; - - g_atomic_int_inc (&counter); - - gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, - (GstPadProbeCallback) cb_blocked, pipeline, NULL); - - /* try to link to the video pad */ - gst_pad_link (pad, sinkpad); -} - -/* called when uridecodebin has created all pads */ -static void -cb_no_more_pads (GstElement *element, - gpointer user_data) -{ - GstElement *pipeline = GST_ELEMENT (user_data); - - if (prerolled) - return; - - dec_counter (pipeline); -} - -/* called when a new message is posted on the bus */ -static void -cb_message (GstBus *bus, - GstMessage *message, - gpointer user_data) -{ - GstElement *pipeline = GST_ELEMENT (user_data); - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR: - g_print ("we received an error!\n"); - g_main_loop_quit (loop); - break; - case GST_MESSAGE_EOS: - g_print ("we reached EOS\n"); - g_main_loop_quit (loop); - break; - case GST_MESSAGE_APPLICATION: - { - if (gst_message_has_name (message, "ExPrerolled")) { - /* it's our message */ - g_print ("we are all prerolled, do seek\n"); - gst_element_seek (pipeline, - 1.0, GST_FORMAT_TIME, - GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, - GST_SEEK_TYPE_SET, 2 * GST_SECOND, - GST_SEEK_TYPE_SET, 5 * GST_SECOND); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); - } - break; - } - default: - break; - } -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstElement *pipeline, *src, *csp, *vs, *sink; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - if (argc < 2) { - g_print ("usage: %s ", argv[0]); - return -1; - } - - /* build */ - pipeline = gst_pipeline_new ("my-pipeline"); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_signal_watch (bus); - g_signal_connect (bus, "message", (GCallback) cb_message, - pipeline); - - src = gst_element_factory_make ("uridecodebin", "src"); - if (src == NULL) - g_error ("Could not create 'uridecodebin' element"); - - g_object_set (src, "uri", argv[1], NULL); - - csp = gst_element_factory_make ("videoconvert", "csp"); - if (csp == NULL) - g_error ("Could not create 'videoconvert' element"); - - vs = gst_element_factory_make ("videoscale", "vs"); - if (csp == NULL) - g_error ("Could not create 'videoscale' element"); - - sink = gst_element_factory_make ("autovideosink", "sink"); - if (sink == NULL) - g_error ("Could not create 'autovideosink' element"); - - gst_bin_add_many (GST_BIN (pipeline), src, csp, vs, sink, NULL); - - /* can't link src yet, it has no pads */ - gst_element_link_many (csp, vs, sink, NULL); - - sinkpad = gst_element_get_static_pad (csp, "sink"); - - /* for each pad block that is installed, we will increment - * the counter. for each pad block that is signaled, we - * decrement the counter. When the counter is 0 we post - * an app message to tell the app that all pads are - * blocked. Start with 1 that is decremented when no-more-pads - * is signaled to make sure that we only post the message - * after no-more-pads */ - g_atomic_int_set (&counter, 1); - - g_signal_connect (src, "pad-added", - (GCallback) cb_pad_added, pipeline); - g_signal_connect (src, "no-more-pads", - (GCallback) cb_no_more_pads, pipeline); - - gst_element_set_state (pipeline, GST_STATE_PAUSED); - - g_main_loop_run (loop); - - gst_element_set_state (pipeline, GST_STATE_NULL); - - gst_object_unref (sinkpad); - gst_object_unref (bus); - gst_object_unref (pipeline); - g_main_loop_unref (loop); - - return 0; -} -]]> - - - - Note that we use a custom application message to signal the - main thread that the uridecidebin is prerolled. The main thread - will then issue a flushing seek to the requested region. The - flush will temporarily unblock the pad and reblock them when - new data arrives again. We detect this second block to remove - the probes. Then we set the pipeline to PLAYING and it should - play from 2 to 5 seconds, then EOS and exit the application. - - - - - - Manually adding or removing data from/to a pipeline - - Many people have expressed the wish to use their own sources to inject - data into a pipeline. Some people have also expressed the wish to grab - the output in a pipeline and take care of the actual output inside - their application. While either of these methods are strongly - discouraged, &GStreamer; offers support for this. - Beware! You need to know what you are doing. Since - you don't have any support from a base class you need to thoroughly - understand state changes and synchronization. If it doesn't work, - there are a million ways to shoot yourself in the foot. It's always - better to simply write a plugin and have the base class manage it. - See the Plugin Writer's Guide for more information on this topic. Also - see the next section, which will explain how to embed plugins statically - in your application. - - - There's two possible elements that you can use for the above-mentioned - purposes. Those are called appsrc (an imaginary source) - and appsink (an imaginary sink). The same method applies - to each of those elements. Here, we will discuss how to use those - elements to insert (using appsrc) or grab (using appsink) data from a - pipeline, and how to set negotiation. - - - Both appsrc and appsink provide 2 sets of API. One API uses standard - GObject (action) signals and properties. The same API is also - available as a regular C api. The C api is more performant but - requires you to link to the app library in order to use the elements. - - - - Inserting data with appsrc - - First we look at some examples for appsrc, which lets you insert data - into the pipeline from the application. Appsrc has some configuration - options that define how it will operate. You should decide about the - following configurations: - - - - - Will the appsrc operate in push or pull mode. The stream-type - property can be used to control this. stream-type of - random-access will activate pull mode scheduling - while the other stream-types activate push mode. - - - - - The caps of the buffers that appsrc will push out. This needs to - be configured with the caps property. The caps must be set to a - fixed caps and will be used to negotiate a format downstream. - - - - - If the appsrc operates in live mode or not. This can be configured - with the is-live property. When operating in live-mode it is - important to configure the min-latency and max-latency in appsrc. - The min-latency should be set to the amount of time it takes between - capturing a buffer and when it is pushed inside appsrc. - In live mode, you should timestamp the buffers with the pipeline - running-time when the first byte of the buffer was captured before - feeding them to appsrc. You can let appsrc do the timestaping with - the do-timestamp property (but then the min-latency must be set - to 0 because it timestamps based on the running-time when the buffer - entered appsrc). - - - - - The format of the SEGMENT event that appsrc will push. The format - has implications for how the running-time of the buffers will - be calculated so you must be sure you understand this. For - live sources you probably want to set the format property to - GST_FORMAT_TIME. For non-live source it depends on the media type - that you are handling. If you plan to timestamp the buffers, you - should probably put a GST_FORMAT_TIME format, otherwise - GST_FORMAT_BYTES might be appropriate. - - - - - If appsrc operates in random-access mode, it is important to configure - the size property of appsrc with the number of bytes in the stream. - This will allow downstream elements to know the size of the media and - alows them to seek to the end of the stream when needed. - - - - - The main way of handling data to appsrc is by using the function - gst_app_src_push_buffer () or by emiting the - push-buffer action signal. This will put the buffer onto a queue from - which appsrc will read from in its streaming thread. It is important - to note that data transport will not happen from the thread that - performed the push-buffer call. - - - The max-bytes property controls how much data can be - queued in appsrc before appsrc considers the queue full. A filled - internal queue will always signal the enough-data - signal, which signals the application that it should stop pushing - data into appsrc. The block property will cause appsrc to - block the push-buffer method until free data becomes available again. - - - When the internal queue is running out of data, the - need-data signal is emitted, which signals the application - that it should start pushing more data into appsrc. - - - In addition to the need-data and enough-data - signals, appsrc can emit the seek-data signal when the - stream-mode property is set to seekable - or random-access. The signal argument will contain the - new desired position in the stream expressed in the unit set with the - format property. After receiving the seek-data signal, - the application should push-buffers from the new position. - - - When the last byte is pushed into appsrc, you must call - gst_app_src_end_of_stream () to make it send - an EOS downstream. - - - These signals allow the application to operate appsrc in push and - pull mode as will be explained next. - - - - Using appsrc in push mode - - When appsrc is configured in push mode (stream-type is stream or - seekable), the application repeatedly calls the push-buffer method - with a new buffer. Optionally, the queue size in the appsrc can be - controlled with the enough-data and need-data signals by respectively - stopping/starting the push-buffer calls. The value of the - min-percent property defines how empty the internal appsrc queue - needs to be before the need-data signal will be fired. You can set - this to some value >0 to avoid completely draining the queue. - - - When the stream-type is set to seekable, don't forget to implement - a seek-data callback. - - - Use this model when implementing various network protocols or - hardware devices. - - - - - Using appsrc in pull mode - - In the pull model, data is fed to appsrc from the need-data signal - handler. You should push exactly the amount of bytes requested in the - need-data signal. You are only allowed to push less bytes when you are - at the end of the stream. - - - Use this model for file access or other randomly accessable sources. - - - - - Appsrc example - - This example application will generate black/white (it switches - every second) video to an Xv-window output by using appsrc as a - source with caps to force a format. We use a colorspace - conversion element to make sure that we feed the right format to - your X server. We configure a video stream with a variable framerate - (0/1) and we set the timestamps on the outgoing buffers in such - a way that we play 2 frames per second. - - - Note how we use the pull mode method of pushing new buffers into - appsrc although appsrc is running in push mode. - - - - - -static GMainLoop *loop; - -static void -cb_need_data (GstElement *appsrc, - guint unused_size, - gpointer user_data) -{ - static gboolean white = FALSE; - static GstClockTime timestamp = 0; - GstBuffer *buffer; - guint size; - GstFlowReturn ret; - - size = 385 * 288 * 2; - - buffer = gst_buffer_new_allocate (NULL, size, NULL); - - /* this makes the image black/white */ - gst_buffer_memset (buffer, 0, white ? 0xff : 0x0, size); - - white = !white; - - GST_BUFFER_PTS (buffer) = timestamp; - GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2); - - timestamp += GST_BUFFER_DURATION (buffer); - - g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret); - gst_buffer_unref (buffer); - - if (ret != GST_FLOW_OK) { - /* something wrong, stop pushing */ - g_main_loop_quit (loop); - } -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstElement *pipeline, *appsrc, *conv, *videosink; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* setup pipeline */ - pipeline = gst_pipeline_new ("pipeline"); - appsrc = gst_element_factory_make ("appsrc", "source"); - conv = gst_element_factory_make ("videoconvert", "conv"); - videosink = gst_element_factory_make ("xvimagesink", "videosink"); - - /* setup */ - g_object_set (G_OBJECT (appsrc), "caps", - gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, "RGB16", - "width", G_TYPE_INT, 384, - "height", G_TYPE_INT, 288, - "framerate", GST_TYPE_FRACTION, 0, 1, - NULL), NULL); - gst_bin_add_many (GST_BIN (pipeline), appsrc, conv, videosink, NULL); - gst_element_link_many (appsrc, conv, videosink, NULL); - - /* setup appsrc */ - g_object_set (G_OBJECT (appsrc), - "stream-type", 0, - "format", GST_FORMAT_TIME, NULL); - g_signal_connect (appsrc, "need-data", G_CALLBACK (cb_need_data), NULL); - - /* play */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - g_main_loop_run (loop); - - /* clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - g_main_loop_unref (loop); - - return 0; - } -]]> - - - - - - - Grabbing data with appsink - - Unlike appsrc, appsink is a little easier to use. It also supports - a pull and push based model of getting data from the pipeline. - - - The normal way of retrieving samples from appsink is by using the - gst_app_sink_pull_sample() and - gst_app_sink_pull_preroll() methods or by using - the pull-sample and pull-preroll - signals. These methods block until a sample becomes available in the - sink or when the sink is shut down or reaches EOS. - - - Appsink will internally use a queue to collect buffers from the - streaming thread. If the application is not pulling samples fast - enough, this queue will consume a lot of memory over time. The - max-buffers property can be used to limit the queue - size. The drop property controls whether the - streaming thread blocks or if older buffers are dropped when the - maximum queue size is reached. Note that blocking the streaming thread - can negatively affect real-time performance and should be avoided. - - - If a blocking behaviour is not desirable, setting the - emit-signals property to TRUE will make appsink emit - the new-sample and new-preroll signals - when a sample can be pulled without blocking. - - - The caps property on appsink can be used to control - the formats that appsink can receive. This property can contain - non-fixed caps, the format of the pulled samples can be obtained by - getting the sample caps. - - - If one of the pull-preroll or pull-sample methods return NULL, the - appsink is stopped or in the EOS state. You can check for the EOS state - with the eos property or with the - gst_app_sink_is_eos() method. - - - The eos signal can also be used to be informed when the EOS state is - reached to avoid polling. - - - Consider configuring the following properties in the appsink: - - - - - The sync property if you want to have the sink - base class synchronize the buffer against the pipeline clock - before handing you the sample. - - - - - Enable Quality-of-Service with the qos property. - If you are dealing with raw video frames and let the base class - sycnhronize on the clock, it might be a good idea to also let - the base class send QOS events upstream. - - - - - The caps property that contains the accepted caps. Upstream elements - will try to convert the format so that it matches the configured - caps on appsink. You must still check the - GstSample to get the actual caps of the - buffer. - - - - - - Appsink example - - What follows is an example on how to capture a snapshot of a video - stream using appsink. - - - - -#ifdef HAVE_GTK -#include -#endif - -#include - -#define CAPS "video/x-raw,format=RGB,width=160,pixel-aspect-ratio=1/1" - -int -main (int argc, char *argv[]) -{ - GstElement *pipeline, *sink; - gint width, height; - GstSample *sample; - gchar *descr; - GError *error = NULL; - gint64 duration, position; - GstStateChangeReturn ret; - gboolean res; - GstMapInfo map; - - gst_init (&argc, &argv); - - if (argc != 2) { - g_print ("usage: %s \n Writes snapshot.png in the current directory\n", - argv[0]); - exit (-1); - } - - /* create a new pipeline */ - descr = - g_strdup_printf ("uridecodebin uri=%s ! videoconvert ! videoscale ! " - " appsink name=sink caps=\"" CAPS "\"", argv[1]); - pipeline = gst_parse_launch (descr, &error); - - if (error != NULL) { - g_print ("could not construct pipeline: %s\n", error->message); - g_clear_error (&error); - exit (-1); - } - - /* get sink */ - sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); - - /* set to PAUSED to make the first frame arrive in the sink */ - ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); - switch (ret) { - case GST_STATE_CHANGE_FAILURE: - g_print ("failed to play the file\n"); - exit (-1); - case GST_STATE_CHANGE_NO_PREROLL: - /* for live sources, we need to set the pipeline to PLAYING before we can - * receive a buffer. We don't do that yet */ - g_print ("live sources not supported yet\n"); - exit (-1); - default: - break; - } - /* This can block for up to 5 seconds. If your machine is really overloaded, - * it might time out before the pipeline prerolled and we generate an error. A - * better way is to run a mainloop and catch errors there. */ - ret = gst_element_get_state (pipeline, NULL, NULL, 5 * GST_SECOND); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_print ("failed to play the file\n"); - exit (-1); - } - - /* get the duration */ - gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration); - - if (duration != -1) - /* we have a duration, seek to 5% */ - position = duration * 5 / 100; - else - /* no duration, seek to 1 second, this could EOS */ - position = 1 * GST_SECOND; - - /* seek to the a position in the file. Most files have a black first frame so - * by seeking to somewhere else we have a bigger chance of getting something - * more interesting. An optimisation would be to detect black images and then - * seek a little more */ - gst_element_seek_simple (pipeline, GST_FORMAT_TIME, - GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH, position); - - /* get the preroll buffer from appsink, this block untils appsink really - * prerolls */ - g_signal_emit_by_name (sink, "pull-preroll", &sample, NULL); - - /* if we have a buffer now, convert it to a pixbuf. It's possible that we - * don't have a buffer because we went EOS right away or had an error. */ - if (sample) { - GstBuffer *buffer; - GstCaps *caps; - GstStructure *s; - - /* get the snapshot buffer format now. We set the caps on the appsink so - * that it can only be an rgb buffer. The only thing we have not specified - * on the caps is the height, which is dependant on the pixel-aspect-ratio - * of the source material */ - caps = gst_sample_get_caps (sample); - if (!caps) { - g_print ("could not get snapshot format\n"); - exit (-1); - } - s = gst_caps_get_structure (caps, 0); - - /* we need to get the final caps on the buffer to get the size */ - res = gst_structure_get_int (s, "width", &width); - res |= gst_structure_get_int (s, "height", &height); - if (!res) { - g_print ("could not get snapshot dimension\n"); - exit (-1); - } - - /* create pixmap from buffer and save, gstreamer video buffers have a stride - * that is rounded up to the nearest multiple of 4 */ - buffer = gst_sample_get_buffer (sample); - /* Mapping a buffer can fail (non-readable) */ - if (gst_buffer_map (buffer, &map, GST_MAP_READ)) { -#ifdef HAVE_GTK - pixbuf = gdk_pixbuf_new_from_data (map.data, - GDK_COLORSPACE_RGB, FALSE, 8, width, height, - GST_ROUND_UP_4 (width * 3), NULL, NULL); - - /* save the pixbuf */ - gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL); -#endif - gst_buffer_unmap (buffer, &map); - } - gst_sample_unref (sample); - } else { - g_print ("could not make snapshot\n"); - } - - /* cleanup and exit */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - - exit (0); -} -]]> - - - - - - - - Forcing a format - - Sometimes you'll want to set a specific format, for example a video - size and format or an audio bitsize and number of channels. You can - do this by forcing a specific GstCaps on - the pipeline, which is possible by using - filtered caps. You can set a filtered caps on - a link by using the capsfilter element in between the - two elements, and specifying a GstCaps as - caps property on this element. It will then - only allow types matching that specified capability set for - negotiation. See also . - - - - Changing format in a PLAYING pipeline - - It is also possible to dynamically change the format in a pipeline - while PLAYING. This can simply be done by changing the caps - property on a capsfilter. The capsfilter will send a RECONFIGURE - event upstream that will make the upstream element attempt to - renegotiate a new format and allocator. This only works if - the upstream element is not using fixed caps on the source pad. - - - Below is an example of how you can change the caps of a pipeline - while in the PLAYING state: - - - - - -#include - -#define MAX_ROUND 100 - -int -main (int argc, char **argv) -{ - GstElement *pipe, *filter; - GstCaps *caps; - gint width, height; - gint xdir, ydir; - gint round; - GstMessage *message; - - gst_init (&argc, &argv); - - pipe = gst_parse_launch_full ("videotestsrc ! capsfilter name=filter ! " - "ximagesink", NULL, GST_PARSE_FLAG_NONE, NULL); - g_assert (pipe != NULL); - - filter = gst_bin_get_by_name (GST_BIN (pipe), "filter"); - g_assert (filter); - - width = 320; - height = 240; - xdir = ydir = -10; - - for (round = 0; round < MAX_ROUND; round++) { - gchar *capsstr; - g_print ("resize to %dx%d (%d/%d) \r", width, height, round, MAX_ROUND); - - /* we prefer our fixed width and height but allow other dimensions to pass - * as well */ - capsstr = g_strdup_printf ("video/x-raw, width=(int)%d, height=(int)%d", - width, height); - - caps = gst_caps_from_string (capsstr); - g_free (capsstr); - g_object_set (filter, "caps", caps, NULL); - gst_caps_unref (caps); - - if (round == 0) - gst_element_set_state (pipe, GST_STATE_PLAYING); - - width += xdir; - if (width >= 320) - xdir = -10; - else if (width < 200) - xdir = 10; - - height += ydir; - if (height >= 240) - ydir = -10; - else if (height < 150) - ydir = 10; - - message = - gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, - 50 * GST_MSECOND); - if (message) { - g_print ("got error \n"); - - gst_message_unref (message); - } - } - g_print ("done \n"); - - gst_object_unref (filter); - gst_element_set_state (pipe, GST_STATE_NULL); - gst_object_unref (pipe); - - return 0; -} -]]> - - - - Note how we use gst_bus_poll() with a - small timeout to get messages and also introduce a short - sleep. - - - It is possible to set multiple caps for the capsfilter separated - with a ;. The capsfilter will try to renegotiate to the first - possible format from the list. - - - - - - Dynamically changing the pipeline - - In this section we talk about some techniques for dynamically - modifying the pipeline. We are talking specifically about changing - the pipeline while it is in the PLAYING state without interrupting - the flow. - - - There are some important things to consider when building dynamic - pipelines: - - - - - When removing elements from the pipeline, make sure that there - is no dataflow on unlinked pads because that will cause a fatal - pipeline error. Always block source pads (in push mode) or - sink pads (in pull mode) before unlinking pads. - See also . - - - - - When adding elements to a pipeline, make sure to put the element - into the right state, usually the same state as the parent, before - allowing dataflow the element. When an element is newly created, - it is in the NULL state and will return an error when it - receives data. - See also . - - - - - When adding elements to a pipeline, &GStreamer; will by default - set the clock and base-time on the element to the current values - of the pipeline. This means that the element will be able to - construct the same pipeline running-time as the other elements - in the pipeline. This means that sinks will synchronize buffers - like the other sinks in the pipeline and that sources produce - buffers with a running-time that matches the other sources. - - - - - When unlinking elements from an upstream chain, always make sure - to flush any queued data in the element by sending an EOS event - down the element sink pad(s) and by waiting that the EOS leaves - the elements (with an event probe). - - - If you do not do this, you will lose the data which is buffered - by the unlinked element. This can result in a simple frame loss - (one or more video frames, several milliseconds of audio). However - if you remove a muxer (and in some cases an encoder or similar elements) - from the pipeline, you risk getting a corrupted file which could not be - played properly, as some relevant metadata (header, seek/index tables, internal - sync tags) will not be stored or updated properly. - - - See also . - - - - - A live source will produce buffers with a running-time of the - current running-time in the pipeline. - - - A pipeline without a live source produces buffers with a - running-time starting from 0. Likewise, after a flushing seek, - those pipelines reset the running-time back to 0. - - - The running-time can be changed with - gst_pad_set_offset (). It is important to - know the running-time of the elements in the pipeline in order - to maintain synchronization. - - - - - Adding elements might change the state of the pipeline. Adding a - non-prerolled sink, for example, brings the pipeline back to the - prerolling state. Removing a non-prerolled sink, for example, might - change the pipeline to PAUSED and PLAYING state. - - - Adding a live source cancels the preroll stage and put the pipeline - to the playing state. Adding a live source or other live elements - might also change the latency of a pipeline. - - - Adding or removing elements to the pipeline might change the clock - selection of the pipeline. If the newly added element provides a clock, - it might be worth changing the clock in the pipeline to the new - clock. If, on the other hand, the element that provides the clock - for the pipeline is removed, a new clock has to be selected. - - - - - Adding and removing elements might cause upstream or downstream - elements to renegotiate caps and or allocators. You don't really - need to do anything from the application, plugins largely - adapt themself to the new pipeline topology in order to optimize - their formats and allocation strategy. - - - What is important is that when you add, remove or change elements - in the pipeline, it is possible that the pipeline needs to - negotiate a new format and this can fail. Usually you can fix this - by inserting the right converter elements where needed. - See also . - - - - - - &GStreamer; offers support for doing about any dynamic pipeline - modification but it requires you to know a bit of details before - you can do this without causing pipeline errors. In the following - sections we will demonstrate a couple of typical use-cases. - - - - Changing elements in a pipeline - - In the next example we look at the following chain of elements: - - - - ----. .----------. .---- - - element1 | | element2 | | element3 - src -> sink src -> sink - - ----' '----------' '---- - - - - We want to change element2 by element4 while the pipeline is in - the PLAYING state. Let's say that element2 is a visualization and - that you want to switch the visualization in the pipeline. - - - We can't just unlink element2's sinkpad from element1's source - pad because that would leave element1's source pad - unlinked and would cause a streaming error in the pipeline when - data is pushed on the source pad. - The technique is to block the dataflow from element1's source pad - before we change element2 by element4 and then resume dataflow - as shown in the following steps: - - - - - Block element1's source pad with a blocking pad probe. When the - pad is blocked, the probe callback will be called. - - - - - Inside the block callback nothing is flowing between element1 - and element2 and nothing will flow until unblocked. - - - - - Unlink element1 and element2. - - - - - Make sure data is flushed out of element2. Some elements might - internally keep some data, you need to make sure not to lose data - by forcing it out of element2. You can do this by pushing EOS into - element2, like this: - - - - - Put an event probe on element2's source pad. - - - - - Send EOS to element2's sinkpad. This makes sure the all the - data inside element2 is forced out. - - - - - Wait for the EOS event to appear on element2's source pad. - When the EOS is received, drop it and remove the event - probe. - - - - - - - Unlink element2 and element3. You can now also remove element2 - from the pipeline and set the state to NULL. - - - - - Add element4 to the pipeline, if not already added. Link element4 - and element3. Link element1 and element4. - - - - - Make sure element4 is in the same state as the rest of the elements - in the pipeline. It should be at least in the PAUSED state before - it can receive buffers and events. - - - - - Unblock element1's source pad probe. This will let new data into - element4 and continue streaming. - - - - - The above algorithm works when the source pad is blocked, i.e. when - there is dataflow in the pipeline. If there is no dataflow, there is - also no point in changing the element (just yet) so this algorithm can - be used in the PAUSED state as well. - - - Let show you how this works with an example. This example changes the - video effect on a simple pipeline every second. - - - - - -static gchar *opt_effects = NULL; - -#define DEFAULT_EFFECTS "identity,exclusion,navigationtest," \ - "agingtv,videoflip,vertigotv,gaussianblur,shagadelictv,edgetv" - -static GstPad *blockpad; -static GstElement *conv_before; -static GstElement *conv_after; -static GstElement *cur_effect; -static GstElement *pipeline; - -static GQueue effects = G_QUEUE_INIT; - -static GstPadProbeReturn -event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) -{ - GMainLoop *loop = user_data; - GstElement *next; - - if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS) - return GST_PAD_PROBE_PASS; - - gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info)); - - /* push current effect back into the queue */ - g_queue_push_tail (&effects, gst_object_ref (cur_effect)); - /* take next effect from the queue */ - next = g_queue_pop_head (&effects); - if (next == NULL) { - GST_DEBUG_OBJECT (pad, "no more effects"); - g_main_loop_quit (loop); - return GST_PAD_PROBE_DROP; - } - - g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME (cur_effect), - GST_OBJECT_NAME (next)); - - gst_element_set_state (cur_effect, GST_STATE_NULL); - - /* remove unlinks automatically */ - GST_DEBUG_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, cur_effect); - gst_bin_remove (GST_BIN (pipeline), cur_effect); - - GST_DEBUG_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next); - gst_bin_add (GST_BIN (pipeline), next); - - GST_DEBUG_OBJECT (pipeline, "linking.."); - gst_element_link_many (conv_before, next, conv_after, NULL); - - gst_element_set_state (next, GST_STATE_PLAYING); - - cur_effect = next; - GST_DEBUG_OBJECT (pipeline, "done"); - - return GST_PAD_PROBE_DROP; -} - -static GstPadProbeReturn -pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) -{ - GstPad *srcpad, *sinkpad; - - GST_DEBUG_OBJECT (pad, "pad is blocked now"); - - /* remove the probe first */ - gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info)); - - /* install new probe for EOS */ - srcpad = gst_element_get_static_pad (cur_effect, "src"); - gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK | - GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, event_probe_cb, user_data, NULL); - gst_object_unref (srcpad); - - /* push EOS into the element, the probe will be fired when the - * EOS leaves the effect and it has thus drained all of its data */ - sinkpad = gst_element_get_static_pad (cur_effect, "sink"); - gst_pad_send_event (sinkpad, gst_event_new_eos ()); - gst_object_unref (sinkpad); - - return GST_PAD_PROBE_OK; -} - -static gboolean -timeout_cb (gpointer user_data) -{ - gst_pad_add_probe (blockpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, - pad_probe_cb, user_data, NULL); - - return TRUE; -} - -static gboolean -bus_cb (GstBus * bus, GstMessage * msg, gpointer user_data) -{ - GMainLoop *loop = user_data; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR:{ - GError *err = NULL; - gchar *dbg; - - gst_message_parse_error (msg, &err, &dbg); - gst_object_default_error (msg->src, err, dbg); - g_clear_error (&err); - g_free (dbg); - g_main_loop_quit (loop); - break; - } - default: - break; - } - return TRUE; -} - -int -main (int argc, char **argv) -{ - GOptionEntry options[] = { - {"effects", 'e', 0, G_OPTION_ARG_STRING, &opt_effects, - "Effects to use (comma-separated list of element names)", NULL}, - {NULL} - }; - GOptionContext *ctx; - GError *err = NULL; - GMainLoop *loop; - GstElement *src, *q1, *q2, *effect, *filter1, *filter2, *sink; - gchar **effect_names, **e; - - 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", err->message); - g_clear_error (&err); - g_option_context_free (ctx); - return 1; - } - g_option_context_free (ctx); - - if (opt_effects != NULL) - effect_names = g_strsplit (opt_effects, ",", -1); - else - effect_names = g_strsplit (DEFAULT_EFFECTS, ",", -1); - - for (e = effect_names; e != NULL && *e != NULL; ++e) { - GstElement *el; - - el = gst_element_factory_make (*e, NULL); - if (el) { - g_print ("Adding effect '%s'\n", *e); - g_queue_push_tail (&effects, el); - } - } - - pipeline = gst_pipeline_new ("pipeline"); - - src = gst_element_factory_make ("videotestsrc", NULL); - g_object_set (src, "is-live", TRUE, NULL); - - filter1 = gst_element_factory_make ("capsfilter", NULL); - gst_util_set_object_arg (G_OBJECT (filter1), "caps", - "video/x-raw, width=320, height=240, " - "format={ I420, YV12, YUY2, UYVY, AYUV, Y41B, Y42B, " - "YVYU, Y444, v210, v216, NV12, NV21, UYVP, A420, YUV9, YVU9, IYU1 }"); - - q1 = gst_element_factory_make ("queue", NULL); - - blockpad = gst_element_get_static_pad (q1, "src"); - - conv_before = gst_element_factory_make ("videoconvert", NULL); - - effect = g_queue_pop_head (&effects); - cur_effect = effect; - - conv_after = gst_element_factory_make ("videoconvert", NULL); - - q2 = gst_element_factory_make ("queue", NULL); - - filter2 = gst_element_factory_make ("capsfilter", NULL); - gst_util_set_object_arg (G_OBJECT (filter2), "caps", - "video/x-raw, width=320, height=240, " - "format={ RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR }"); - - sink = gst_element_factory_make ("ximagesink", NULL); - - gst_bin_add_many (GST_BIN (pipeline), src, filter1, q1, conv_before, effect, - conv_after, q2, sink, NULL); - - gst_element_link_many (src, filter1, q1, conv_before, effect, conv_after, - q2, sink, NULL); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - loop = g_main_loop_new (NULL, FALSE); - - gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), bus_cb, loop); - - g_timeout_add_seconds (1, timeout_cb, loop); - - g_main_loop_run (loop); - - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - - return 0; -} -]]> - - - - Note how we added videoconvert elements before and after the effect. - This is needed because some elements might operate in different - colorspaces than other elements. By inserting the conversion elements - you ensure that the right format can be negotiated at any time. - - - - - diff --git a/docs/manual/advanced-dparams.xml b/docs/manual/advanced-dparams.xml deleted file mode 100644 index 4459e01f98..0000000000 --- a/docs/manual/advanced-dparams.xml +++ /dev/null @@ -1,102 +0,0 @@ - - Dynamic Controllable Parameters - - - Getting Started - - The controller subsystem offers a lightweight way to adjust gobject - properties over stream-time. Normally these properties are changed using - g_object_set(). Timing those calls reliably so that - the changes affect certain stream times is close to impossible. The - controller takes time into account. It works by attaching control-sources - to properties using control-bindings. Control-sources provide values for a - given time-stamp that are usually in the range of 0.0 to 1.0. - Control-bindings map the control-value to a gobject property they are bound to - - converting the type and scaling to the target property value range. - At run-time the elements continuously pull values changes for the current - stream-time to update the gobject properties. GStreamer includes a few - different control-sources and control-bindings already, but applications can - define their own by sub-classing from the respective base classes. - - - Most parts of the controller mechanism is implemented in GstObject. Also the - base classes for control-sources and control-bindings are included in the core - library. The existing implementations are contained within the - gstcontroller library. - You need to include the header in your application's source file: - - -... -#include <gst/gst.h> -#include <gst/controller/gstinterpolationcontrolsource.h> -#include <gst/controller/gstdirectcontrolbinding.h> -... - - - Your application should link to the shared library - gstreamer-controller. One can get the required flag for - compiler and linker by using pkg-config for gstreamer-controller-1.0. - - - - - Setting up parameter control - - If we have our pipeline set up and want to control some parameters, we first - need to create a control-source. Lets use an interpolation control-source: - - - csource = gst_interpolation_control_source_new (); - g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); - - - Now we need to attach the control-source to the gobject property. This is done - with a control-binding. One control source can be attached to several object - properties (even in different objects) using separate control-bindings. - - - gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource)); - - - This type control-source takes new property values from a list of time-stamped - parameter changes. The source can e.g. fill gaps by smoothing parameter changes - This behavior can be configured by setting the mode property of the - control-source. Other control sources e.g. produce a stream of values by - calling sin() function. They have parameters to control - e.g. the frequency. As control-sources are GstObjects too, one can attach - control-sources to these properties too. - - - Now we can set some control points. These are time-stamped gdouble values and - are usually in the range of 0.0 to 1.0. A value of 1.0 is later mapped to the - maximum value in the target properties value range. - The values become active when the timestamp is reached. They still stay - in the list. If e.g. the pipeline runs a loop (using a segmented seek), - the control-curve gets repeated as well. - - - GstTimedValueControlSource *tv_csource = (GstTimedValueControlSource *)csource; - gst_timed_value_control_source_set (tv_csource, 0 * GST_SECOND, 0.0); - gst_timed_value_control_source_set (tv_csource, 1 * GST_SECOND, 1.0); - - - Now everything is ready to play. If the control-source is e.g. bound to a - volume property, we will head a fade-in over 1 second. One word of caution, - the volume element that comes with gstreamer has a value range of 0.0 to 4.0 - on its volume property. If the above control-source is attached to the property - the volume will ramp up to 400%! - - - One final note - the controller subsystem has a built-in live-mode. Even though - a property has a control-source assigned one can change the GObject property - through the g_object_set(). - This is highly useful when binding the GObject properties to GUI widgets. - When the user adjusts the value with the widget, one can set the GObject - property and this remains active until the next programmed control-source - value overrides it. This also works with smoothed parameters. It does not - work for control-sources that constantly update the property (e.g. the - lfo_control_source). - - - - diff --git a/docs/manual/advanced-interfaces.xml b/docs/manual/advanced-interfaces.xml deleted file mode 100644 index ef41f4caee..0000000000 --- a/docs/manual/advanced-interfaces.xml +++ /dev/null @@ -1,82 +0,0 @@ - - Interfaces - - - In , you have learned how - to use GObject properties as a simple way to do - interaction between applications and elements. This method suffices for - the simple'n'straight settings, but fails for anything more complicated - than a getter and setter. For the more complicated use cases, &GStreamer; - uses interfaces based on the GObject GTypeInterface - type. - - - - Most of the interfaces handled here will not contain any example code. - See the API references for details. Here, we will just describe the - scope and purpose of each interface. - - - - The URI interface - - - In all examples so far, we have only supported local files through the - filesrc element. &GStreamer;, obviously, supports many - more location sources. However, we don't want applications to need to - know any particular element implementation details, such as element - names for particular network source types and so on. Therefore, there - is a URI interface, which can be used to get the source element that - supports a particular URI type. There is no strict rule for URI naming, - but in general we follow naming conventions that others use, too. For - example, assuming you have the correct plugins installed, &GStreamer; - supports file:///<path>/<file>, - http://<host>/<path>/<file>, - mms://<host>/<path>/<file>, and so on. - - - In order to get the source or sink element supporting a particular URI, - use gst_element_make_from_uri (), with the URI - type being either GST_URI_SRC for a source - element, or GST_URI_SINK for a sink element. - - - You can convert filenames to and from URIs using GLib's - g_filename_to_uri () and - g_uri_to_filename (). - - - - - The Color Balance interface - - - The colorbalance interface is a way to control video-related properties - on an element, such as brightness, contrast and so on. It's sole - reason for existence is that, as far as its authors know, there's no - way to dynamically register properties using - GObject. - - - The colorbalance interface is implemented by several plugins, including - xvimagesink and the Video4linux2 elements. - - - - - The Video Overlay interface - - - The Video Overlay interface was created to solve the problem of embedding - video streams in an application window. The application provides an - window handle to the element implementing this interface to draw on, and - the element will then use this window handle to draw on rather than creating - a new toplevel window. This is useful to embed video in video players. - - - This interface is implemented by, amongst others, the Video4linux2 - elements and by ximagesink, xvimagesink and sdlvideosink. - - - diff --git a/docs/manual/advanced-metadata.xml b/docs/manual/advanced-metadata.xml deleted file mode 100644 index f975409e6a..0000000000 --- a/docs/manual/advanced-metadata.xml +++ /dev/null @@ -1,196 +0,0 @@ - - Metadata - - - &GStreamer; makes a clear distinction between two types of metadata, and - has support for both types. The first is stream tags, which describe the - content of a stream in a non-technical way. Examples include the author - of a song, the title of that very same song or the album it is a part of. - The other type of metadata is stream-info, which is a somewhat technical - description of the properties of a stream. This can include video size, - audio samplerate, codecs used and so on. Tags are handled using the - &GStreamer; tagging system. Stream-info can be retrieved from a - GstPad by getting the current (negotiated) - GstCaps for that pad. - - - - Metadata reading - - - Stream information can most easily be read by reading it from a - GstPad. This has already been discussed before - in . Therefore, we will skip - it here. Note that this requires access to all pads of which you - want stream information. - - - - Tag reading is done through a bus in &GStreamer;, which has been - discussed previously in . You can - listen for GST_MESSAGE_TAG messages and handle - them as you wish. - - - Note, however, that the GST_MESSAGE_TAG - message may be fired multiple times in the pipeline. It is the - application's responsibility to put all those tags together and - display them to the user in a nice, coherent way. Usually, using - gst_tag_list_merge () is a good enough way - of doing this; make sure to empty the cache when loading a new song, - or after every few minutes when listening to internet radio. Also, - make sure you use GST_TAG_MERGE_PREPEND as - merging mode, so that a new title (which came in later) has a - preference over the old one for display. - - - The following example will extract tags from a file and print them: - - -/* compile with: - * gcc -o tags tags.c `pkg-config --cflags --libs gstreamer-1.0` */ -#include <gst/gst.h> - -static void -print_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) -{ - int i, num; - - num = gst_tag_list_get_tag_size (list, tag); - for (i = 0; i < num; ++i) { - const GValue *val; - - /* Note: when looking for specific tags, use the gst_tag_list_get_xyz() API, - * we only use the GValue approach here because it is more generic */ - val = gst_tag_list_get_value_index (list, tag, i); - if (G_VALUE_HOLDS_STRING (val)) { - g_print ("\t%20s : %s\n", tag, g_value_get_string (val)); - } else if (G_VALUE_HOLDS_UINT (val)) { - g_print ("\t%20s : %u\n", tag, g_value_get_uint (val)); - } else if (G_VALUE_HOLDS_DOUBLE (val)) { - g_print ("\t%20s : %g\n", tag, g_value_get_double (val)); - } else if (G_VALUE_HOLDS_BOOLEAN (val)) { - g_print ("\t%20s : %s\n", tag, - (g_value_get_boolean (val)) ? "true" : "false"); - } else if (GST_VALUE_HOLDS_BUFFER (val)) { - GstBuffer *buf = gst_value_get_buffer (val); - guint buffer_size = gst_buffer_get_size (buf); - - g_print ("\t%20s : buffer of size %u\n", tag, buffer_size); - } else if (GST_VALUE_HOLDS_DATE_TIME (val)) { - GstDateTime *dt = g_value_get_boxed (val); - gchar *dt_str = gst_date_time_to_iso8601_string (dt); - - g_print ("\t%20s : %s\n", tag, dt_str); - g_free (dt_str); - } else { - g_print ("\t%20s : tag of type '%s'\n", tag, G_VALUE_TYPE_NAME (val)); - } - } -} - -static void -on_new_pad (GstElement * dec, GstPad * pad, GstElement * fakesink) -{ - GstPad *sinkpad; - - sinkpad = gst_element_get_static_pad (fakesink, "sink"); - if (!gst_pad_is_linked (sinkpad)) { - if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) - g_error ("Failed to link pads!"); - } - gst_object_unref (sinkpad); -} - -int -main (int argc, char ** argv) -{ - GstElement *pipe, *dec, *sink; - GstMessage *msg; - gchar *uri; - - gst_init (&argc, &argv); - - if (argc < 2) - g_error ("Usage: %s FILE or URI", argv[0]); - - if (gst_uri_is_valid (argv[1])) { - uri = g_strdup (argv[1]); - } else { - uri = gst_filename_to_uri (argv[1], NULL); - } - - pipe = gst_pipeline_new ("pipeline"); - - dec = gst_element_factory_make ("uridecodebin", NULL); - g_object_set (dec, "uri", uri, NULL); - gst_bin_add (GST_BIN (pipe), dec); - - sink = gst_element_factory_make ("fakesink", NULL); - gst_bin_add (GST_BIN (pipe), sink); - - g_signal_connect (dec, "pad-added", G_CALLBACK (on_new_pad), sink); - - gst_element_set_state (pipe, GST_STATE_PAUSED); - - while (TRUE) { - GstTagList *tags = NULL; - - msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), - GST_CLOCK_TIME_NONE, - GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_TAG | GST_MESSAGE_ERROR); - - if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_TAG) /* error or async_done */ - break; - - gst_message_parse_tag (msg, &tags); - - g_print ("Got tags from element %s:\n", GST_OBJECT_NAME (msg->src)); - gst_tag_list_foreach (tags, print_one_tag, NULL); - g_print ("\n"); - gst_tag_list_unref (tags); - - gst_message_unref (msg); - } - - if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { - GError *err = NULL; - - gst_message_parse_error (msg, &err, NULL); - g_printerr ("Got error: %s\n", err->message); - g_error_free (err); - } - - gst_message_unref (msg); - gst_element_set_state (pipe, GST_STATE_NULL); - gst_object_unref (pipe); - g_free (uri); - return 0; -} - - - - - Tag writing - - - Tag writing is done using the GstTagSetter - interface. All that's required is a tag-set-supporting element in - your pipeline. In order to see if any of the elements in your - pipeline supports tag writing, you can use the function - gst_bin_iterate_all_by_interface (pipeline, - GST_TYPE_TAG_SETTER). On the resulting element, usually - an encoder or muxer, you can use gst_tag_setter_merge - () (with a taglist) or gst_tag_setter_add - () (with individual tags) to set tags on it. - - - A nice extra feature in &GStreamer; tag support is that tags are - preserved in pipelines. This means that if you transcode one file - containing tags into another media type, and that new media type - supports tags too, then the tags will be handled as part of the - data stream and be merged into the newly written media file, too. - - - diff --git a/docs/manual/advanced-position.xml b/docs/manual/advanced-position.xml deleted file mode 100644 index 1786339a49..0000000000 --- a/docs/manual/advanced-position.xml +++ /dev/null @@ -1,235 +0,0 @@ - - Position tracking and seeking - - - So far, we've looked at how to create a pipeline to do media processing - and how to make it run. Most application developers will be interested - in providing feedback to the user on media progress. Media players, for - example, will want to show a slider showing the progress in the song, - and usually also a label indicating stream length. Transcoding - applications will want to show a progress bar on how much percent of - the task is done. &GStreamer; has built-in support for doing all this - using a concept known as querying. Since seeking - is very similar, it will be discussed here as well. Seeking is done - using the concept of events. - - - - Querying: getting the position or length of a stream - - - Querying is defined as requesting a specific stream property related - to progress tracking. This includes getting the length of a stream (if - available) or getting the current position. Those stream properties - can be retrieved in various formats such as time, audio samples, video - frames or bytes. The function most commonly used for this is - gst_element_query (), although some convenience - wrappers are provided as well (such as - gst_element_query_position () and - gst_element_query_duration ()). You can generally - query the pipeline directly, and it'll figure out the internal details - for you, like which element to query. - - - - Internally, queries will be sent to the sinks, and - dispatched backwards until one element can handle it; - that result will be sent back to the function caller. Usually, that - is the demuxer, although with live sources (from a webcam), it is the - source itself. - - - - -#include <gst/gst.h> - - - - -static gboolean -cb_print_position (GstElement *pipeline) -{ - gint64 pos, len; - - if (gst_element_query_position (pipeline, GST_FORMAT_TIME, &pos) - && gst_element_query_duration (pipeline, GST_FORMAT_TIME, &len)) { - g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r", - GST_TIME_ARGS (pos), GST_TIME_ARGS (len)); - } - - /* call me again */ - return TRUE; -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstElement *pipeline; - -[..] - - /* run pipeline */ - g_timeout_add (200, (GSourceFunc) cb_print_position, pipeline); - g_main_loop_run (loop); - -[..] - -} - - - - - Events: seeking (and more) - - - Events work in a very similar way as queries. Dispatching, for - example, works exactly the same for events (and also has the same - limitations), and they can similarly be sent to the toplevel pipeline - and it will figure out everything for you. Although there are more - ways in which applications and elements can interact using events, - we will only focus on seeking here. This is done using the seek-event. - A seek-event contains a playback rate, a seek offset format (which is - the unit of the offsets to follow, e.g. time, audio samples, video - frames or bytes), optionally a set of seeking-related flags (e.g. - whether internal buffers should be flushed), a seek method (which - indicates relative to what the offset was given), and seek offsets. - The first offset (cur) is the new position to seek to, while - the second offset (stop) is optional and specifies a position where - streaming is supposed to stop. Usually it is fine to just specify - GST_SEEK_TYPE_NONE and -1 as end_method and end offset. The behaviour - of a seek is also wrapped in the gst_element_seek (). - - - -static void -seek_to_time (GstElement *pipeline, - gint64 time_nanoseconds) -{ - if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, time_nanoseconds, - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) { - g_print ("Seek failed!\n"); - } -} - - - Seeks with the GST_SEEK_FLAG_FLUSH should be done when the pipeline is - in PAUSED or PLAYING state. The pipeline will automatically go to preroll - state until the new data after the seek will cause the pipeline to preroll - again. After the pipeline is prerolled, it will go back to the state - (PAUSED or PLAYING) it was in when the seek was executed. You can wait - (blocking) for the seek to complete with - gst_element_get_state() or by waiting for the - ASYNC_DONE message to appear on the bus. - - - - Seeks without the GST_SEEK_FLAG_FLUSH should only be done when the - pipeline is in the PLAYING state. Executing a non-flushing seek in the - PAUSED state might deadlock because the pipeline streaming threads might - be blocked in the sinks. - - - - It is important to realise that seeks will not happen instantly in the - sense that they are finished when the function - gst_element_seek () returns. Depending on the - specific elements involved, the actual seeking might be done later in - another thread (the streaming thread), and it might take a short time - until buffers from the new seek position will reach downstream elements - such as sinks (if the seek was non-flushing then it might take a bit - longer). - - - - It is possible to do multiple seeks in short time-intervals, such as - a direct response to slider movement. After a seek, internally, the - pipeline will be paused (if it was playing), the position will be - re-set internally, the demuxers and decoders will decode from the new - position onwards and this will continue until all sinks have data - again. If it was playing originally, it will be set to playing again, - too. Since the new position is immediately available in a video output, - you will see the new frame, even if your pipeline is not in the playing - state. - - - - diff --git a/docs/manual/advanced-threads.xml b/docs/manual/advanced-threads.xml deleted file mode 100644 index cf2f50cff3..0000000000 --- a/docs/manual/advanced-threads.xml +++ /dev/null @@ -1,481 +0,0 @@ - - Threads - - &GStreamer; is inherently multi-threaded, and is fully thread-safe. - Most threading internals are hidden from the application, which should - make application development easier. However, in some cases, applications - may want to have influence on some parts of those. &GStreamer; allows - applications to force the use of multiple threads over some parts of - a pipeline. - See . - - - &GStreamer; can also notify you when threads are created so that you can - configure things such as the thread priority or the threadpool to use. - See . - - - - Scheduling in &GStreamer; - - Each element in the &GStreamer; pipeline decides how it is going to - be scheduled. Elements can choose if their pads are to be scheduled - push-based or pull-based. An element can, for example, choose to start - a thread to start pulling from the sink pad or/and start pushing on - the source pad. An element can also choose to use the upstream or - downstream thread for its data processing in push and pull mode - respectively. &GStreamer; does not pose any restrictions on how the - element chooses to be scheduled. See the Plugin Writer Guide for more - details. - - - What will happen in any case is that some elements will start a thread - for their data processing, called the streaming threads. - The streaming threads, or GstTask objects, are - created from a GstTaskPool when the element - needs to make a streaming thread. In the next section we see how we - can receive notifications of the tasks and pools. - - - - - Configuring Threads in &GStreamer; - - A STREAM_STATUS message is posted on the bus to inform you about the - status of the streaming threads. You will get the following information - from the message: - - - - When a new thread is about to be created, you will be notified - of this with a GST_STREAM_STATUS_TYPE_CREATE type. It is then - possible to configure a GstTaskPool in - the GstTask. The custom taskpool will - provide custom threads for the task to implement the streaming - threads. - - - This message needs to be handled synchronously if you want to - configure a custom taskpool. If you don't configure the taskpool - on the task when this message returns, the task will use its - default pool. - - - - - When a thread is entered or left. This is the moment where you - could configure thread priorities. You also get a notification - when a thread is destroyed. - - - - - You get messages when the thread starts, pauses and stops. This - could be used to visualize the status of streaming threads in - a gui application. - - - - - - - - We will now look at some examples in the next sections. - - - - Boost priority of a thread - - .----------. .----------. - | faksesrc | | fakesink | - | src->sink | - '----------' '----------' - - - Let's look at the simple pipeline above. We would like to boost - the priority of the streaming thread. - It will be the fakesrc element that starts the streaming thread for - generating the fake data pushing them to the peer fakesink. - The flow for changing the priority would go like this: - - - - - When going from READY to PAUSED state, fakesrc will require a - streaming thread for pushing data into the fakesink. It will - post a STREAM_STATUS message indicating its requirement for a - streaming thread. - - - - - The application will react to the STREAM_STATUS messages with a - sync bus handler. It will then configure a custom - GstTaskPool on the - GstTask inside the message. The custom - taskpool is responsible for creating the threads. In this - example we will make a thread with a higher priority. - - - - - Alternatively, since the sync message is called in the thread - context, you can use thread ENTER/LEAVE notifications to - change the priority or scheduling pollicy of the current thread. - - - - - In a first step we need to implement a custom - GstTaskPool that we can configure on the task. - Below is the implementation of a GstTaskPool - subclass that uses pthreads to create a SCHED_RR real-time thread. - Note that creating real-time threads might require extra priveleges. - - - - - - - - -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 */ -} - -static void -default_cleanup (GstTaskPool * 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; - - tid = g_slice_new0 (TestRTId); - - pthread_attr_init (&attr); - if ((res = pthread_attr_setschedpolicy (&attr, SCHED_RR)) != 0) - g_warning ("setschedpolicy: failure: %p", g_strerror (res)); - - param.sched_priority = 50; - if ((res = pthread_attr_setschedparam (&attr, ¶m)) != 0) - g_warning ("setschedparam: failure: %p", g_strerror (res)); - - if ((res = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0) - g_warning ("setinheritsched: failure: %p", g_strerror (res)); - - 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; - - pthread_join (tid->thread, NULL); - - g_slice_free (TestRTId, tid); -} - -static void -test_rt_pool_class_init (TestRTPoolClass * klass) -{ - GstTaskPoolClass *gsttaskpool_class; - - gsttaskpool_class = (GstTaskPoolClass *) klass; - - 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) -{ -} - -GstTaskPool * -test_rt_pool_new (void) -{ - GstTaskPool *pool; - - pool = g_object_new (TEST_TYPE_RT_POOL, NULL); - - return pool; -} -]]> - - - - The important function to implement when writing an taskpool is the - push function. The implementation should start a thread - that calls the given function. More involved implementations might - want to keep some threads around in a pool because creating and - destroying threads is not always the fastest operation. - - - In a next step we need to actually configure the custom taskpool when - the fakesrc needs it. For this we intercept the STREAM_STATUS messages - with a sync handler. - - - - - - - - Note that this program likely needs root permissions in order to - create real-time threads. When the thread can't be created, the - state change function will fail, which we catch in the application - above. - - - When there are multiple threads in the pipeline, you will receive - multiple STREAM_STATUS messages. You should use the owner of the - message, which is likely the pad or the element that starts the - thread, to figure out what the function of this thread is in the - context of the application. - - - - - - When would you want to force a thread? - - We have seen that threads are created by elements but it is also - possible to insert elements in the pipeline for the sole purpose of - forcing a new thread in the pipeline. - - - There are several reasons to force the use of threads. However, - for performance reasons, you never want to use one thread for every - element out there, since that will create some overhead. - Let's now list some situations where threads can be particularly - useful: - - - - - Data buffering, for example when dealing with network streams or - when recording data from a live stream such as a video or audio - card. Short hickups elsewhere in the pipeline will not cause data - loss. See also about network - buffering with queue2. - -
- Data buffering, from a networked source - - - - - -
- -
- - - Synchronizing output devices, e.g. when playing a stream containing - both video and audio data. By using threads for both outputs, they - will run independently and their synchronization will be better. - -
- Synchronizing audio and video sinks - - - - - -
-
-
- - - - Above, we've mentioned the queue element several times - now. A queue is the thread boundary element through which you can - force the use of threads. It does so by using a classic - provider/consumer model as learned in threading classes at - universities all around the world. By doing this, it acts both as a - means to make data throughput between threads threadsafe, and it can - also act as a buffer. Queues have several GObject - properties to be configured for specific uses. For example, you can set - lower and upper thresholds for the element. If there's less data than - the lower threshold (default: disabled), it will block output. If - there's more data than the upper threshold, it will block input or - (if configured to do so) drop data. - - - To use a queue (and therefore force the use of two distinct threads - in the pipeline), one can simply create a queue element - and put this in as part of the pipeline. &GStreamer; will take care of - all threading details internally. - -
- -
diff --git a/docs/manual/appendix-checklist.xml b/docs/manual/appendix-checklist.xml deleted file mode 100644 index 538ba5e84d..0000000000 --- a/docs/manual/appendix-checklist.xml +++ /dev/null @@ -1,204 +0,0 @@ - - Things to check when writing an application - - This chapter contains a fairly random selection of things that can be - useful to keep in mind when writing &GStreamer;-based applications. It's - up to you how much you're going to use the information provided here. - We will shortly discuss how to debug pipeline problems using &GStreamer; - applications. Also, we will touch upon how to acquire knowledge about - plugins and elements and how to test simple pipelines before building - applications around them. - - - - Good programming habits - - - - Always add a GstBus handler to your - pipeline. Always report errors in your application, and try - to do something with warnings and information messages, too. - - - - - Always check return values of &GStreamer; functions. Especially, - check return values of gst_element_link () - and gst_element_set_state (). - - - - - Dereference return values of all functions returning a non-base - type, such as gst_element_get_pad (). Also, - always free non-const string returns, such as - gst_object_get_name (). - - - - - Always use your pipeline object to keep track of the current state - of your pipeline. Don't keep private variables in your application. - Also, don't update your user interface if a user presses the - play button. Instead, listen for the - state-changed message on the - GstBus and only update the user interface - whenever this message is received. - - - - - Report all bugs that you find in &GStreamer; bugzilla at - http://bugzilla.gnome.org/. - - - - - - - Debugging - - Applications can make use of the extensive &GStreamer; debugging system - to debug pipeline problems. Elements will write output to this system - to log what they're doing. It's not used for error reporting, but it - is very useful for tracking what an element is doing exactly, which - can come in handy when debugging application issues (such as failing - seeks, out-of-sync media, etc.). - - - Most &GStreamer;-based applications accept the commandline option - and related family members. The - list consists of a comma-separated list of category/level pairs, - which can set the debugging level for a specific debugging category. - For example, would turn - on debugging for the Ogg demuxer element. You can use wildcards as - well. A debugging level of 0 will turn off all debugging, and a level - of 9 will turn on all debugging. Intermediate values only turn on - some debugging (based on message severity; 2, for example, will only - display errors and warnings). Here's a list of all available options: - - - - - - will print available debug - categories and exit. - - - - - - will set the default debug level (which can range from 0 (no - output) to 9 (everything)). - - - - - - takes a comma-separated list of category_name:level pairs to - set specific levels for the individual categories. Example: - . Alternatively, you - can also set the GST_DEBUG environment - variable, which has the same effect. - - - - - will disable color debugging. - You can also set the GST_DEBUG_NO_COLOR environment variable to 1 - if you want to disable colored debug output permanently. Note that - if you are disabling color purely to avoid messing up your pager - output, try using less -R. - - - - - - will change debug log coloring mode. MODE - can be one of the following: , - , , - , . - You can also set the GST_DEBUG_COLOR_MODE environment variable - if you want to change colored debug output permanently. Note that - if you are disabling color purely to avoid messing up your pager - output, try using less -R. - - - - - disables debugging altogether. - - - - - enables printout of errors while - loading &GStreamer; plugins. - - - - - - - - Conversion plugins - - &GStreamer; contains a bunch of conversion plugins that most - applications will find useful. Specifically, those are videoscalers - (videoscale), colorspace convertors (videoconvert), audio format - convertors and channel resamplers (audioconvert) and audio samplerate - convertors (audioresample). Those convertors don't do anything when not - required, they will act in passthrough mode. They will activate when - the hardware doesn't support a specific request, though. All - applications are recommended to use those elements. - - - - - Utility applications provided with &GStreamer; - - &GStreamer; comes with a default set of command-line utilities that - can help in application development. We will discuss only - gst-launch and gst-inspect here. - - - - <command>gst-launch</command> - - gst-launch is a simple script-like commandline - application that can be used to test pipelines. For example, the - command gst-launch audiotestsrc ! audioconvert ! - audio/x-raw,channels=2 ! alsasink will run - a pipeline which generates a sine-wave audio stream and plays it - to your ALSA audio card. gst-launch also allows - the use of threads (will be used automatically as required or as queue - elements are inserted in the pipeline) and bins (using brackets, so - ( and )). You can use dots to imply - padnames on elements, - or even omit the padname to automatically select a pad. Using - all this, the pipeline - gst-launch filesrc location=file.ogg ! oggdemux name=d - d. ! queue ! theoradec ! videoconvert ! xvimagesink - d. ! queue ! vorbisdec ! audioconvert ! audioresample ! alsasink - will play an Ogg file - containing a Theora video-stream and a Vorbis audio-stream. You can - also use autopluggers such as decodebin on the commandline. See the - manual page of gst-launch for more information. - - - - - <command>gst-inspect</command> - - gst-inspect can be used to inspect all properties, - signals, dynamic parameters and the object hierarchy of an element. - This can be very useful to see which GObject - properties or which signals (and using what arguments) an element - supports. Run gst-inspect fakesrc to get an idea - of what it does. See the manual page of gst-inspect - for more information. - - - - - diff --git a/docs/manual/appendix-compiling.xml b/docs/manual/appendix-compiling.xml deleted file mode 100644 index 2d83c989be..0000000000 --- a/docs/manual/appendix-compiling.xml +++ /dev/null @@ -1,76 +0,0 @@ - - Compiling - - This section talks about the different things you can do when building - and shipping your applications and plugins. - - - - Embedding static elements in your application - - The Plugin - Writer's Guide describes in great detail how to write elements - for the &GStreamer; framework. In this section, we will solely discuss - how to embed such elements statically in your application. This can be - useful for application-specific elements that have no use elsewhere in - &GStreamer;. - - - Dynamically loaded plugins contain a structure that's defined using - GST_PLUGIN_DEFINE (). This structure is loaded - when the plugin is loaded by the &GStreamer; core. The structure - contains an initialization function (usually called - plugin_init) that will be called right after that. - It's purpose is to register the elements provided by the plugin with - the &GStreamer; framework. - If you want to embed elements directly in - your application, the only thing you need to do is to replace - GST_PLUGIN_DEFINE () with a call to - gst_plugin_register_static (). As soon as you - call gst_plugin_register_static (), the elements - will from then on be available like any other element, without them - having to be dynamically loadable libraries. In the example below, you - would be able to call gst_element_factory_make - ("my-element-name", "some-name") to create an instance of the - element. - - - - - - - diff --git a/docs/manual/appendix-integration.xml b/docs/manual/appendix-integration.xml deleted file mode 100644 index 64b9ed81f0..0000000000 --- a/docs/manual/appendix-integration.xml +++ /dev/null @@ -1,331 +0,0 @@ - - Integration - - &GStreamer; tries to integrate closely with operating systems (such - as Linux and UNIX-like operating systems, OS X or Windows) and desktop - environments (such as GNOME or KDE). In this chapter, we'll mention - some specific techniques to integrate your application with your - operating system or desktop environment of choice. - - - - - - - - Linux and UNIX-like operating systems - - &GStreamer; provides a basic set of elements that are useful when - integrating with Linux or a UNIX-like operating system. - - - - - For audio input and output, &GStreamer; provides input and - output elements for several audio subsystems. Amongst others, - &GStreamer; includes elements for ALSA (alsasrc, - alsasink), OSS (osssrc, osssink) Pulesaudio (pulsesrc, pulsesink) - and Sun audio (sunaudiosrc, sunaudiomixer, sunaudiosink). - - - - - For video input, &GStreamer; contains source elements for - Video4linux2 (v4l2src, v4l2element, v4l2sink). - - - - - For video output, &GStreamer; provides elements for output - to X-windows (ximagesink), Xv-windows (xvimagesink; for - hardware-accelerated video), direct-framebuffer (dfbimagesink) - and openGL image contexts (glsink). - - - - - - - - - - - GNOME desktop - - &GStreamer; has been the media backend of the GNOME desktop since GNOME-2.2 - onwards. Nowadays, a whole bunch of GNOME applications make use of - &GStreamer; for media-processing, including (but not limited to) - Rhythmbox, - Videos - and Sound - Juicer. - - - Most of these GNOME applications make use of some specific techniques - to integrate as closely as possible with the GNOME desktop: - - - - - GNOME applications usually call gtk_init () - to parse command-line options and initialize GTK. &GStreamer; - applications would normally call gst_init () - to do the same for GStreamer. - This would mean that only one of the two can parse command-line - options. To work around this issue, &GStreamer; can provide a - GLib GOptionGroup which can be passed to - gnome_program_init (). The following - example requires GTK 2.6 or newer (previous GTK versions - do not support command line parsing via GOption yet) - - -#include <gtk/gtk.h> -#include <gst/gst.h> - -static gchar **cmd_filenames = NULL; - -static GOptionEntries cmd_options[] = { - /* here you can add command line options for your application. Check - * the GOption section in the GLib API reference for a more elaborate - * example of how to add your own command line options here */ - - /* at the end we have a special option that collects all remaining - * command line arguments (like filenames) for us. If you don't - * need this, you can safely remove it */ - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &cmd_filenames, - "Special option that collects any remaining arguments for us" }, - - /* mark the end of the options array with a NULL option */ - { NULL, } -}; - -/* this should usually be defined in your config.h */ -#define VERSION "0.0.1" - -gint -main (gint argc, gchar **argv) -{ - GOptionContext *context; - GOptionGroup *gstreamer_group, *gtk_group; - GError *err = NULL; - - context = g_option_context_new ("gtk-demo-app"); - - /* get command line options from GStreamer and add them to the group */ - gstreamer_group = gst_init_get_option_group (); - g_option_context_add_group (context, gstreamer_group); - gtk_group = gtk_get_option_group (TRUE); - g_option_context_add_group (context, gtk_group); - - /* add our own options. If you are using gettext for translation of your - * strings, use GETTEXT_PACKAGE here instead of NULL */ - g_option_context_add_main_entries (context, cmd_options, NULL); - - /* now parse the commandline options, note that this already - * calls gtk_init() and gst_init() */ - if (!g_option_context_parse (ctx, &argc, &argv, &err)) { - g_print ("Error initializing: %s\n", err->message); - g_clear_error (&err); - g_option_context_free (ctx); - exit (1); - } - g_option_context_free (ctx); - - /* any filenames we got passed on the command line? parse them! */ - if (cmd_filenames != NULL) { - guint i, num; - - num = g_strv_length (cmd_filenames); - for (i = 0; i < num; ++i) { - /* do something with the filename ... */ - g_print ("Adding to play queue: %s\n", cmd_filenames[i]); - } - - g_strfreev (cmd_filenames); - cmd_filenames = NULL; - } - -[..] - -} - - - - - GNOME uses Pulseaudio for audio, use the pulsesrc and - pulsesink elements to have access to all the features. - - - - - &GStreamer; provides data input/output elements for use with the - GIO VFS system. These elements are called giosrc - and giosink. - The deprecated GNOME-VFS system is supported too but shouldn't be - used for any new applications. - - - - - - - - - - - - - KDE desktop - - &GStreamer; has been proposed for inclusion in KDE-4.0. Currently, - &GStreamer; is included as an optional component, and it's used by - several KDE applications, including AmaroK, - KMPlayer and - Kaffeine. - - - Although not yet as complete as the GNOME integration bits, there - are already some KDE integration specifics available. This list will - probably grow as &GStreamer; starts to be used in KDE-4.0: - - - - - AmaroK contains a kiosrc element, which is a source element that - integrates with the KDE VFS subsystem KIO. - - - - - - - - - - - OS X - - &GStreamer; provides native video and audio output elements for OS X. - It builds using the standard development tools for OS X. - - - - - - - - - Windows - - - -Note: this section is out of date. GStreamer-1.0 has much better -support for win32 than previous versions though and should usually compile -and work out-of-the-box both using MSYS/MinGW or Microsoft compilers. The -GStreamer web site and the -mailing list -archives are a good place to check the latest win32-related news. - - - - - - &GStreamer; builds using Microsoft Visual C .NET 2003 and using Cygwin. - - - - Building <application>GStreamer</application> under Win32 - -There are different makefiles that can be used to build GStreamer with the usual Microsoft -compiling tools. - -The Makefile is meant to be used with the GNU make program and the free -version of the Microsoft compiler (http://msdn.microsoft.com/visualc/vctoolkit2003/). You also -have to modify your system environment variables to use it from the command-line. You will also -need a working Platform SDK for Windows that is available for free from Microsoft. - -The projects/makefiles will generate automatically some source files needed to compile -GStreamer. That requires that you have installed on your system some GNU tools and that they are -available in your system PATH. - -The GStreamer project depends on other libraries, namely : - -GLib -libxml2 -libintl -libiconv - - -Work is being done to provide pre-compiled GStreamer-1.0 libraries as -a packages for win32. Check the -GStreamer web site and check our -mailing list - for the latest developments in this respect. - - -Notes - -GNU tools needed that you can find on http://gnuwin32.sourceforge.net/ - -GNU flex (tested with 2.5.4) -GNU bison (tested with 1.35) - - -and http://www.mingw.org/ - -GNU make (tested with 3.80) - - -the generated files from the -auto makefiles will be available soon separately on the net -for convenience (people who don't want to install GNU tools). - - - - -Installation on the system - -FIXME: This section needs be updated for GStreamer-1.0. - - - - - - - - diff --git a/docs/manual/appendix-licensing.xml b/docs/manual/appendix-licensing.xml deleted file mode 100644 index 128a6ccbcb..0000000000 --- a/docs/manual/appendix-licensing.xml +++ /dev/null @@ -1,101 +0,0 @@ - -Licensing advisory - - How to license the applications you build with <application>GStreamer</application> - -The licensing of GStreamer is no different from a lot of other libraries -out there like GTK+ or glibc: we use the LGPL. What complicates things -with regards to GStreamer is its plugin-based design and the heavily -patented and proprietary nature of many multimedia codecs. While patents -on software are currently only allowed in a small minority of world -countries (the US and Australia being the most important of those), the -problem is that due to the central place the US hold in the world economy -and the computing industry, software patents are hard to ignore wherever -you are. - -Due to this situation, many companies, including major GNU/Linux -distributions, get trapped in a situation where they either get bad -reviews due to lacking out-of-the-box media playback capabilities (and -attempts to educate the reviewers have met with little success so far), or -go against their own - and the free software movement's - wish to avoid -proprietary software. Due to competitive pressure, most choose to add some -support. Doing that through pure free software solutions would have them -risk heavy litigation and punishment from patent owners. So when the -decision is made to include support for patented codecs, it leaves them -the choice of either using special proprietary applications, or try to -integrate the support for these codecs through proprietary plugins into -the multimedia infrastructure provided by GStreamer. Faced with one of -these two evils the GStreamer community of course prefer the second option. - - -The problem which arises is that most free software and open source -applications developed use the GPL as their license. While this is -generally a good thing, it creates a dilemma for people who want to put -together a distribution. The dilemma they face is that if they include -proprietary plugins in GStreamer to support patented formats in a way that -is legal for them, they do risk running afoul of the GPL license of the -applications. We have gotten some conflicting reports from lawyers on -whether this is actually a problem, but the official stance of the FSF is -that it is a problem. We view the FSF as an authority on this matter, so -we are inclined to follow their interpretation of the GPL license. - - -So what does this mean for you as an application developer? Well, it means -you have to make an active decision on whether you want your application -to be used together with proprietary plugins or not. What you decide here -will also influence the chances of commercial distributions and Unix -vendors shipping your application. The GStreamer community suggest you -license your software using a license that will allow proprietary plugins -to be bundled with GStreamer and your applications, in order to make sure -that as many vendors as possible go with GStreamer instead of less free -solutions. This in turn we hope and think will let GStreamer be a vehicle -for wider use of free formats like the Xiph.org formats. - - -If you do decide that you want to allow for non-free plugins to be used -with your application you have a variety of choices. One of the simplest -is using licenses like LGPL, MPL or BSD for your application instead of -the GPL. Or you can add an exception clause to your GPL license stating -that you except GStreamer plugins from the obligations of the GPL. - - -A good example of such a GPL exception clause would be, using the -Totem video player project as an example: -The authors of the Totem video player project hereby grants permission -for non-GPL-compatible GStreamer plugins to be used and distributed -together with GStreamer and Totem. This permission goes above and beyond -the permissions granted by the GPL license Totem is covered by. - - -Our suggestion among these choices is to use the LGPL license, as it is -what resembles the GPL most and it makes it a good licensing fit with the -major GNU/Linux desktop projects like GNOME and KDE. It also allows you to -share code more openly with projects that have compatible licenses. -Obviously, pure GPL code without the above-mentioned clause is not usable -in your application as such. By choosing the LGPL, there is no need for an -exception clause and thus code can be shared more freely. - - -I have above outlined the practical reasons for why the GStreamer -community suggests you allow non-free plugins to be used with your -applications. We feel that in the multimedia arena, the free software -community is still not strong enough to set the agenda and that blocking -non-free plugins to be used in our infrastructure hurts us more than it -hurts the patent owners and their ilk. - - -This view is not shared by everyone. The Free Software Foundation urges -you to use an unmodified GPL for your applications, so as to push back -against the temptation to use non-free plug-ins. They say that since not -everyone else has the strength to reject them because they are unethical, -they ask your help to give them a legal reason to do so. - - -This advisory is part of a bigger advisory with a FAQ which you can find -on the GStreamer website - - - - - - diff --git a/docs/manual/appendix-porting.xml b/docs/manual/appendix-porting.xml deleted file mode 100644 index 6a8eb097ea..0000000000 --- a/docs/manual/appendix-porting.xml +++ /dev/null @@ -1,316 +0,0 @@ - - Porting 0.8 applications to 0.10 - - This section of the appendix will discuss shortly what changes to - applications will be needed to quickly and conveniently port most - applications from &GStreamer;-0.8 to &GStreamer;-0.10, with references - to the relevant sections in this Application Development Manual - where needed. With this list, it should be possible to port simple - applications to &GStreamer;-0.10 in less than a day. - - - - List of changes - - - - Most functions returning an object or an object property have - been changed to return its own reference rather than a constant - reference of the one owned by the object itself. The reason for - this change is primarily thread safety. This means, effectively, - that return values of functions such as - gst_element_get_pad (), - gst_pad_get_name () and many more like these - have to be free'ed or unreferenced after use. Check the API - references of each function to know for sure whether return - values should be free'ed or not. It is important that all objects - derived from GstObject are ref'ed/unref'ed using gst_object_ref() - and gst_object_unref() respectively (instead of g_object_ref/unref). - - - - - Applications should no longer use signal handlers to be notified - of errors, end-of-stream and other similar pipeline events. - Instead, they should use the GstBus, which - has been discussed in . The bus will - take care that the messages will be delivered in the context of a - main loop, which is almost certainly the application's main thread. - The big advantage of this is that applications no longer need to - be thread-aware; they don't need to use g_idle_add - () in the signal handler and do the actual real work - in the idle-callback. &GStreamer; now does all that internally. - - - - - Related to this, gst_bin_iterate () has been - removed. Pipelines will iterate in their own thread, and applications - can simply run a GMainLoop (or call the - mainloop of their UI toolkit, such as gtk_main - ()). - - - - - State changes can be delayed (ASYNC). Due to the new fully threaded - nature of GStreamer-0.10, state changes are not always immediate, - in particular changes including the transition from READY to PAUSED - state. This means two things in the context of porting applications: - first of all, it is no longer always possible to do - gst_element_set_state () and check for a return - value of GST_STATE_CHANGE_SUCCESS, as the state change might be - delayed (ASYNC) and the result will not be known until later. You - should still check for GST_STATE_CHANGE_FAILURE right away, it is - just no longer possible to assume that everything that is not SUCCESS - means failure. Secondly, state changes might not be immediate, so - your code needs to take that into account. You can wait for a state - change to complete if you use GST_CLOCK_TIME_NONE as timeout interval - with gst_element_get_state (). - - - - - In 0.8, events and queries had to manually be sent to sinks in - pipelines (unless you were using playbin). This is no longer - the case in 0.10. In 0.10, queries and events can be sent to - toplevel pipelines, and the pipeline will do the dispatching - internally for you. This means less bookkeeping in your - application. For a short code example, see . Related, seeking is now - threadsafe, and your video output will show the new video - position's frame while seeking, providing a better user - experience. - - - - - The GstThread object has been removed. - Applications can now simply put elements in a pipeline with - optionally some queue elements in between for - buffering, and &GStreamer; will take care of creating threads - internally. It is still possible to have parts of a pipeline - run in different threads than others, by using the - queue element. See - for details. - - - - - Filtered caps -> capsfilter element (the pipeline syntax for - gst-launch has not changed though). - - - - - libgstgconf-0.10.la does not exist. Use the - gconfvideosink and gconfaudiosink - elements instead, which will do live-updates and require no library - linking. - - - - - The new-pad and state-change signals on - GstElement were renamed to - pad-added and state-changed. - - - - - gst_init_get_popt_table () has been removed - in favour of the new GOption command line option API that was - added to GLib 2.6. gst_init_get_option_group () - is the new GOption-based equivalent to - gst_init_get_ptop_table (). - - - - - - - Porting 0.10 applications to 1.0 - - This section outlines some of the changes necessary to port - applications from &GStreamer;-0.10 to &GStreamer;-1.0. For a - comprehensive and up-to-date list, see the separate - Porting to 1.0 document. - - - It should be possible to port simple applications to - &GStreamer;-1.0 in less than a day. - - - - List of changes - - - - All deprecated methods were removed. Recompile against 0.10 with - GST_DISABLE_DEPRECATED defined (such as by adding - -DGST_DISABLE_DEPRECATED to the compiler flags) and fix issues - before attempting to port to 1.0. - - - - - "playbin2" has been renamed to "playbin", with similar API - - - - - "decodebin2" has been renamed to "decodebin", with similar API. Note - that there is no longer a "new-decoded-pad" signal, just use GstElement's - "pad-added" signal instead (but don't forget to remove the 'gboolean last' - argument from your old signal callback functino signature). - - - - - the names of some "formatted" pad templates has been changed from e.g. - "src%d" to "src%u" or "src_%u" or similar, since we don't want to see - negative numbers in pad names. This mostly affects applications that - create request pads from elements. - - - - - some elements that used to have a single dynamic source pad have a - source pad now. Example: wavparse, id3demux, iceydemux, apedemux. - (This does not affect applications using decodebin or playbin). - - - - - playbin now proxies the GstVideoOverlay (former GstXOverlay) interface, - so most applications can just remove the sync bus handler where they - would set the window ID, and instead just set the window ID on playbin - from the application thread before starting playback. - - - playbin also proxies the GstColorBalance and GstNavigation interfaces, - so applications that use this don't need to go fishing for elements - that may implement those any more, but can just use on playbin - unconditionally. - - - - - multifdsink, tcpclientsink, tcpclientsrc, tcpserversrc the protocol property - is removed, use gdppay and gdpdepay. - - - - - XML serialization was removed. - - - - - Probes and pad blocking was merged into new pad probes. - - - - - Position, duration and convert functions no longer use an inout parameter - for the destination format. - - - - - Video and audio caps were simplified. audio/x-raw-int and audio/x-raw-float - are now all under the audio/x-raw media type. Similarly, video/x-raw-rgb - and video/x-raw-yuv are now video/x-raw. - - - - - ffmpegcolorspace was removed and replaced with videoconvert. - - - - - GstMixerInterface / GstTunerInterface were removed without replacement. - - - - - The GstXOverlay interface was renamed to GstVideoOverlay, and now part - of the video library in gst-plugins-base, as the interfaces library - no longer exists. - - - The name of the GstXOverlay "prepare-xwindow-id" message has changed - to "prepare-window-handle" (and GstXOverlay has been renamed to - GstVideoOverlay). Code that checks for the string directly should be - changed to use gst_is_video_overlay_prepare_window_handle_message(message) - instead. - - - - - The GstPropertyProbe interface was removed. There is no replacement - for it in GStreamer 1.0.x and 1.2.x, but since version 1.4 there is - a more featureful replacement for device discovery and feature - querying provided by GstDeviceMonitor, GstDevice, and friends. See - the - "GStreamer Device Discovery and Device Probing" documentation. - - - - - gst_uri_handler_get_uri() and the get_uri vfunc now return a copy of - the URI string - - - gst_uri_handler_set_uri() and the set_uri vfunc now take an additional - GError argument so the handler can notify the caller why it didn't - accept a particular URI. - - - gst_uri_handler_set_uri() now checks if the protocol of the URI passed - is one of the protocols advertised by the uri handler, so set_uri vfunc - implementations no longer need to check that as well. - - - - - GstTagList is now an opaque mini object instead of being typedefed to a - GstStructure. While it was previously okay (and in some cases required because of - missing taglist API) to cast a GstTagList to a GstStructure or use - gst_structure_* API on taglists, you can no longer do that. Doing so will - cause crashes. - - - Also, tag lists are refcounted now, and can therefore not be freely - modified any longer. Make sure to call gst_tag_list_make_writable (taglist) - before adding, removing or changing tags in the taglist. - - - GST_TAG_IMAGE, GST_TAG_PREVIEW_IMAGE, GST_TAG_ATTACHMENT: many tags that - used to be of type GstBuffer are now of type GstSample (which is basically - a struct containing a buffer alongside caps and some other info). - - - - - GstController has now been merged into GstObject. It does not exists as an - individual object anymore. In addition core contains a GstControlSource base - class and the GstControlBinding. The actual control sources are in the controller - library as before. The 2nd big change is that control sources generate - a sequence of gdouble values and those are mapped to the property type and - value range by GstControlBindings. - - - The whole gst_controller_* API is gone and now available in simplified form - under gst_object_*. ControlSources are now attached via GstControlBinding - to properties. There are no GValue arguments used anymore when programming - control sources. - - - - - diff --git a/docs/manual/appendix-programs.xml b/docs/manual/appendix-programs.xml deleted file mode 100644 index 72eab54562..0000000000 --- a/docs/manual/appendix-programs.xml +++ /dev/null @@ -1,342 +0,0 @@ - - Programs - - - - - <command>gst-launch</command> - - This is a tool that will construct pipelines based on a command-line - syntax. - - - A simple commandline looks like: - - -gst-launch filesrc location=hello.mp3 ! mad ! audioresample ! osssink - - - A more complex pipeline looks like: - - -gst-launch filesrc location=redpill.vob ! dvddemux name=demux \ - demux.audio_00 ! queue ! a52dec ! audioconvert ! audioresample ! osssink \ - demux.video_00 ! queue ! mpeg2dec ! videoconvert ! xvimagesink - - - - - You can also use the parser in you own - code. GStreamer provides a function - gst_parse_launch () that you can use to construct a pipeline. - The following program lets you create an MP3 pipeline using the - gst_parse_launch () function: - - -#include <gst/gst.h> - -int -main (int argc, char *argv[]) -{ - GstElement *pipeline; - GstElement *filesrc; - GstMessage *msg; - GstBus *bus; - GError *error = NULL; - - gst_init (&argc, &argv); - - if (argc != 2) { - g_print ("usage: %s <filename>\n", argv[0]); - return -1; - } - - pipeline = gst_parse_launch ("filesrc name=my_filesrc ! mad ! osssink", &error); - if (!pipeline) { - g_print ("Parse error: %s\n", error->message); - exit (1); - } - - filesrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_filesrc"); - g_object_set (filesrc, "location", argv[1], NULL); - g_object_unref (filesrc); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - bus = gst_element_get_bus (pipeline); - - /* wait until we either get an EOS or an ERROR message. Note that in a real - * program you would probably not use gst_bus_poll(), but rather set up an - * async signal watch on the bus and run a main loop and connect to the - * bus's signals to catch certain messages or all messages */ - msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: { - g_print ("EOS\n"); - break; - } - case GST_MESSAGE_ERROR: { - GError *err = NULL; /* error to show to users */ - gchar *dbg = NULL; /* additional debug string for developers */ - - gst_message_parse_error (msg, &err, &dbg); - if (err) { - g_printerr ("ERROR: %s\n", err->message); - g_error_free (err); - } - if (dbg) { - g_printerr ("[Debug details: %s]\n", dbg); - g_free (dbg); - } - } - default: - g_printerr ("Unexpected message of type %d", GST_MESSAGE_TYPE (msg)); - break; - } - gst_message_unref (msg); - - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - gst_object_unref (bus); - - return 0; -} - - - Note how we can retrieve the filesrc element from the constructed bin using the - element name. - - - Grammar Reference - - The gst-launch syntax is processed by a flex/bison parser. This section - is intended to provide a full specification of the grammar; any deviations from this - specification is considered a bug. - - - Elements - - ... mad ... - - - A bare identifier (a string beginning with a letter and containing - only letters, numbers, dashes, underscores, percent signs, or colons) - will create an element from a given element factory. In this example, - an instance of the "mad" MP3 decoding plugin will be created. - - - - Links - - ... !sink ... - - - An exclamation point, optionally having a qualified pad name (an the name of the pad, - optionally preceded by the name of the element) on both sides, will link two pads. If - the source pad is not specified, a source pad from the immediately preceding element - will be automatically chosen. If the sink pad is not specified, a sink pad from the next - element to be constructed will be chosen. An attempt will be made to find compatible - pads. Pad names may be preceded by an element name, as in - my_element_name.sink_pad. - - - - Properties - - ... location="http://gstreamer.net" ... - - - The name of a property, optionally qualified with an element name, and a value, - separated by an equals sign, will set a property on an element. If the element is not - specified, the previous element is assumed. Strings can optionally be enclosed in - quotation marks. Characters in strings may be escaped with the backtick - (\). If the right-hand side is all digits, it is considered to be an - integer. If it is all digits and a decimal point, it is a double. If it is "true", - "false", "TRUE", or "FALSE" it is considered to be boolean. Otherwise, it is parsed as a - string. The type of the property is determined later on in the parsing, and the value is - converted to the target type. This conversion is not guaranteed to work, it relies on - the g_value_convert routines. No error message will be displayed on an invalid - conversion, due to limitations in the value convert API. - - - - Bins, Threads, and Pipelines - - ( ... ) - - - A pipeline description between parentheses is placed into a bin. The open paren may be - preceded by a type name, as in jackbin.( ... ) to make - a bin of a specified type. Square brackets make pipelines, and curly braces make - threads. The default toplevel bin type is a pipeline, although putting the whole - description within parentheses or braces can override this default. - - - - - - - <command>gst-inspect</command> - - This is a tool to query a plugin or an element about its properties. - - - To query the information about the element mad, you would specify: - - - -gst-inspect mad - - - - Below is the output of a query for the osssink element: - - - -, Wim Taymans - -Plugin Details: - Name: ossaudio - Description: OSS (Open Sound System) support for GStreamer - Filename: /home/wim/gst/head/gst-plugins-good/sys/oss/.libs/libgstossaudio.so - Version: 1.0.0.1 - License: LGPL - Source module: gst-plugins-good - Source release date: 2012-09-25 12:52 (UTC) - Binary package: GStreamer Good Plug-ins git - Origin URL: Unknown package origin - -GObject - +----GInitiallyUnowned - +----GstObject - +----GstElement - +----GstBaseSink - +----GstAudioBaseSink - +----GstAudioSink - +----GstOssSink - -Pad Templates: - SINK template: 'sink' - Availability: Always - Capabilities: - audio/x-raw - format: { S16LE, U16LE, S8, U8 } - layout: interleaved - rate: [ 1, 2147483647 ] - channels: 1 - audio/x-raw - format: { S16LE, U16LE, S8, U8 } - layout: interleaved - rate: [ 1, 2147483647 ] - channels: 2 - channel-mask: 0x0000000000000003 - - -Element Flags: - no flags set - -Element Implementation: - Has change_state() function: gst_audio_base_sink_change_state - -Clocking Interaction: - element is supposed to provide a clock but returned NULL - -Element has no indexing capabilities. -Element has no URI handling capabilities. - -Pads: - SINK: 'sink' - Implementation: - Has chainfunc(): gst_base_sink_chain - Has custom eventfunc(): gst_base_sink_event - Has custom queryfunc(): gst_base_sink_sink_query - Has custom iterintlinkfunc(): gst_pad_iterate_internal_links_default - Pad Template: 'sink' - -Element Properties: - name : The name of the object - flags: readable, writable - String. Default: "osssink0" - parent : The parent of the object - flags: readable, writable - Object of type "GstObject" - sync : Sync on the clock - flags: readable, writable - Boolean. Default: true - max-lateness : Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited) - flags: readable, writable - Integer64. Range: -1 - 9223372036854775807 Default: -1 - qos : Generate Quality-of-Service events upstream - flags: readable, writable - Boolean. Default: false - async : Go asynchronously to PAUSED - flags: readable, writable - Boolean. Default: true - ts-offset : Timestamp offset in nanoseconds - flags: readable, writable - Integer64. Range: -9223372036854775808 - 9223372036854775807 Default: 0 - enable-last-sample : Enable the last-sample property - flags: readable, writable - Boolean. Default: false - last-sample : The last sample received in the sink - flags: readable - Boxed pointer of type "GstSample" - blocksize : Size in bytes to pull per buffer (0 = default) - flags: readable, writable - Unsigned Integer. Range: 0 - 4294967295 Default: 4096 - render-delay : Additional render delay of the sink in nanoseconds - flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 - throttle-time : The time to keep between rendered buffers - flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 - buffer-time : Size of audio buffer in microseconds, this is the minimum latency that the sink reports - flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 200000 - latency-time : The minimum amount of data to write in each iteration in microseconds - flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 10000 - provide-clock : Provide a clock to be used as the global pipeline clock - flags: readable, writable - Boolean. Default: true - slave-method : Algorithm to use to match the rate of the masterclock - flags: readable, writable - Enum "GstAudioBaseSinkSlaveMethod" Default: 1, "skew" - (0): resample - GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE - (1): skew - GST_AUDIO_BASE_SINK_SLAVE_SKEW - (2): none - GST_AUDIO_BASE_SINK_SLAVE_NONE - can-activate-pull : Allow pull-based scheduling - flags: readable, writable - Boolean. Default: false - alignment-threshold : Timestamp alignment threshold in nanoseconds - flags: readable, writable - Unsigned Integer64. Range: 1 - 18446744073709551614 Default: 40000000 - drift-tolerance : Tolerance for clock drift in microseconds - flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 40000 - discont-wait : Window of time in nanoseconds to wait before creating a discontinuity - flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551614 Default: 1000000000 - device : OSS device (usually /dev/dspN) - flags: readable, writable - String. Default: "/dev/dsp" -]]> - - - - To query the information about a plugin, you would do: - - - -gst-inspect gstelements - - - - diff --git a/docs/manual/appendix-quotes.xml b/docs/manual/appendix-quotes.xml deleted file mode 100644 index e0656aff46..0000000000 --- a/docs/manual/appendix-quotes.xml +++ /dev/null @@ -1,350 +0,0 @@ - - Quotes from the Developers - - As well as being a cool piece of software, - GStreamer is a lively project, with - developers from around the globe very actively contributing. - We often hang out on the #gstreamer IRC channel on - irc.freenode.net: the following are a selection of amusing - No guarantee of sense of humour compatibility is given. - quotes from our conversations. - - - - - - 6 Mar 2006 - - -When I opened my eyes I was in a court room. There were masters McIlroy and -Thompson sitting in the jury and master Kernighan too. There were the GStreamer -developers standing in the defendant's place, accused of violating several laws -of Unix philosophy and customer lock-down via running on a proprietary -pipeline, different from that of the Unix systems. I heard Eric Raymond -whispering "got to add this case to my book. - -behdad's blog - - - - - 22 May 2007 - -<__tim> -Uraeus: amusing, isn't it? - -<Uraeus> -__tim: I wrote that :) - -<__tim> -Uraeus: of course you did; your refusal to surrender to the oppressive regime -of the third-person-singular-rule is so unique in its persistence that it's -hard to miss :) - - - - - - - 12 Sep 2005 - -<wingo> -we just need to get rid of that mmap stuff - -<wingo> -i think gnomevfssrc is faster for files even - -<BBB> -wingo, no - -<BBB> -and no - -<wingo> -good points ronald - - - - - - 23 Jun 2005 - - -* wingo back -* thomasvs back ---- You are now known as everybody -* everybody back back -<everybody> now break it down ---- You are now known as thomasvs -* bilboed back ---- bilboed is now known as john-sebastian -* john-sebastian bach ---- john-sebastian is now known as bilboed ---- You are now known as scratch_my -* scratch_my back ---- bilboed is now known as Illbe ---- You are now known as thomasvs -* Illbe back ---- Illbe is now known as bilboed - - - - - 20 Apr 2005 - - - thomas: -jrb, somehow his screenshotsrc grabs whatever X is showing and makes it -available as a stream of frames - - - jrb: -thomas: so, is the point that the screenshooter takes a video? -but won't the dialog be in the video? oh, nevermind. I'll just send mail... - - - thomas: -jrb, well, it would shoot first and ask questions later - - - - - - 2 Nov 2004 - - - zaheerm: -wtay: unfair u fixed the bug i was using as a feature! - - - - - - 14 Oct 2004 - - - * zaheerm -wonders how he can break gstreamer today :) - - - ensonic: -zaheerm, spider is always a good starting point - - - - - - 14 Jun 2004 - - - teuf: ok, things work much better when I don't write incredibly stupid and buggy code - - - thaytan: I find that too - - - - - 23 Nov 2003 - - - Uraeus: ah yes, the sleeping part, my mind - is not multitasking so I was still thinking about exercise - - - dolphy: Uraeus: your mind is multitasking - - - dolphy: Uraeus: you just miss low latency patches - - - - - - 14 Sep 2002 - - - --- wingo-party is now known as - wingo - - - * wingo holds head - - - - - - 4 Jun 2001 - - taaz: you witchdoctors and your voodoo mpeg2 black magic... - omega_: um. I count three, no four different cults there <g> - ajmitch: hehe - omega_: witchdoctors, voodoo, black magic, - omega_: and mpeg - - - - - 16 Feb 2001 - - - wtay: - I shipped a few commerical products to >40000 people now but - GStreamer is way more exciting... - - - - - 16 Feb 2001 - - - * - tool-man - is a gstreamer groupie - - - - - 14 Jan 2001 - - - Omega: - did you run ldconfig? maybe it talks to init? - - - wtay: - not sure, don't think so... - I did run gstreamer-register though :-) - - - Omega: - ah, that did it then ;-) - - - wtay: - right - - - Omega: - probably not, but in case GStreamer starts turning into an OS, someone please let me know? - - - - - 9 Jan 2001 - - - wtay: - me tar, you rpm? - - - wtay: - hehe, forgot "zan" - - - Omega: - ? - - - wtay: - me tar"zan", you ... - - - - - 7 Jan 2001 - - - Omega: - that means probably building an agreggating, cache-massaging - queue to shove N buffers across all at once, forcing cache - transfer. - - - wtay: - never done that before... - - - Omega: - nope, but it's easy to do in gstreamer <g> - - - wtay: - sure, I need to rewrite cp with gstreamer too, someday :-) - - - - - 7 Jan 2001 - - - wtay: - GStreamer; always at least one developer is awake... - - - - - 5/6 Jan 2001 - - - wtay: - we need to cut down the time to create an mp3 player down to - seconds... - - - richardb: - :) - - - Omega: - I'm wanting to something more interesting soon, I did the "draw an mp3 - player in 15sec" back in October '99. - - - wtay: - by the time Omega gets his hands on the editor, you'll see a - complete audio mixer in the editor :-) - - - richardb: - Well, it clearly has the potential... - - - Omega: - Working on it... ;-) - - - - - 28 Dec 2000 - - - MPAA: - We will sue you now, you have violated our IP rights! - - - wtay: - hehehe - - - MPAA: - How dare you laugh at us? We have lawyers! We have Congressmen! We have LARS! - - - wtay: - I'm so sorry your honor - - - MPAA: - Hrumph. - - - * - wtay - bows before thy - - - - - - diff --git a/docs/manual/base.css b/docs/manual/base.css deleted file mode 100644 index a24c078ad3..0000000000 --- a/docs/manual/base.css +++ /dev/null @@ -1,3 +0,0 @@ -pre.programlisting { - background: #E8E8FF; -} diff --git a/docs/manual/basics-bins.xml b/docs/manual/basics-bins.xml deleted file mode 100644 index 882f3d153c..0000000000 --- a/docs/manual/basics-bins.xml +++ /dev/null @@ -1,185 +0,0 @@ - - Bins - - A bin is a container element. You can add elements to a bin. Since a - bin is an element itself, a bin can be handled in the same way as any - other element. Therefore, the whole previous chapter () applies to bins as well. - - - - What are bins - - Bins allow you to combine a group of linked elements into one - logical element. You do not deal with the individual elements - anymore but with just one element, the bin. We will see that - this is extremely powerful when you are going to construct - complex pipelines since it allows you to break up the pipeline - in smaller chunks. - - - The bin will also manage the elements contained in it. It will - perform state changes on the elements as well as collect and - forward bus messages. - - -
- Visualisation of a bin with some elements in it - - - - - -
- - - There is one specialized type of bin available to the - &GStreamer; programmer: - - - - - A pipeline: a generic container that manages the synchronization - and bus messages of the contained elements. The toplevel bin has - to be a pipeline, every application thus needs at least one of - these. - - - -
- - - Creating a bin - - Bins are created in the same way that other elements are created, - i.e. using an element factory. There are also convenience functions - available (gst_bin_new () and - gst_pipeline_new ()). - To add elements to a bin or remove elements from a - bin, you can use gst_bin_add () and - gst_bin_remove (). Note that the bin that you - add an element to will take ownership of that element. If you - destroy the bin, the element will be dereferenced with it. If you - remove an element from a bin, it will be dereferenced automatically. - - -#include <gst/gst.h> - -int -main (int argc, - char *argv[]) -{ - GstElement *bin, *pipeline, *source, *sink; - - /* init */ - gst_init (&argc, &argv); - - /* create */ - pipeline = gst_pipeline_new ("my_pipeline"); - bin = gst_bin_new ("my_bin"); - source = gst_element_factory_make ("fakesrc", "source"); - sink = gst_element_factory_make ("fakesink", "sink"); - - /* First add the elements to the bin */ - gst_bin_add_many (GST_BIN (bin), source, sink, NULL); - /* add the bin to the pipeline */ - gst_bin_add (GST_BIN (pipeline), bin); - - /* link the elements */ - gst_element_link (source, sink); - -[..] - -} - - - There are various functions to lookup elements in a bin. The most - commonly used are gst_bin_get_by_name () and - gst_bin_get_by_interface (). You can also - iterate over all elements that a bin contains using the function - gst_bin_iterate_elements (). See the API references - of GstBin - for details. - - - - - Custom bins - - The application programmer can create custom bins packed with elements - to perform a specific task. This allows you, for example, to write - an Ogg/Vorbis decoder with just the following lines of code: - - -int -main (int argc, - char *argv[]) -{ - GstElement *player; - - /* init */ - gst_init (&argc, &argv); - - /* create player */ - player = gst_element_factory_make ("oggvorbisplayer", "player"); - - /* set the source audio file */ - g_object_set (player, "location", "helloworld.ogg", NULL); - - /* start playback */ - gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING); -[..] -} - - - (This is a silly example of course, there already exists a much more - powerful and versatile custom bin like this: the playbin element.) - - - Custom bins can be created with a plugin or from the application. You - will find more information about creating custom bin in the Plugin - Writers Guide. - - - Examples of such custom bins are the playbin and uridecodebin elements from - gst-plugins-base. - - - - Bins manage states of their children - - Bins manage the state of all elements contained in them. If you set - a bin (or a pipeline, which is a special top-level type of bin) to - a certain target state using gst_element_set_state (), - it will make sure all elements contained within it will also be set - to this state. This means it's usually only necessary to set the state - of the top-level pipeline to start up the pipeline or shut it down. - - - The bin will perform the state changes on all its children from the - sink element to the source element. This ensures that the downstream - element is ready to receive data when the upstream element is brought - to PAUSED or PLAYING. Similarly when shutting down, the sink elements - will be set to READY or NULL first, which will cause the upstream - elements to receive a FLUSHING error and stop the streaming threads - before the elements are set to the READY or NULL state. - - - Note, however, that if elements are added to a bin or pipeline that's - already running, , e.g. from within a "pad-added" - signal callback, its state will not automatically be brought in line with - the current state or target state of the bin or pipeline it was added to. - Instead, you have to need to set it to the desired target state yourself - using gst_element_set_state () or - gst_element_sync_state_with_parent () when adding - elements to an already-running pipeline. - - -
diff --git a/docs/manual/basics-bus.xml b/docs/manual/basics-bus.xml deleted file mode 100644 index d040c8dcbd..0000000000 --- a/docs/manual/basics-bus.xml +++ /dev/null @@ -1,289 +0,0 @@ - - Bus - - A bus is a simple system that takes care of forwarding messages from - the streaming threads to an application in its own thread context. The - advantage of a bus is that an application does not need to be - thread-aware in order to use &GStreamer;, even though &GStreamer; - itself is heavily threaded. - - - Every pipeline contains a bus by default, so applications do not need - to create a bus or anything. The only thing applications should do is - set a message handler on a bus, which is similar to a signal handler - to an object. When the mainloop is running, the bus will periodically - be checked for new messages, and the callback will be called when any - message is available. - - - - How to use a bus - - There are two different ways to use a bus: - - - - Run a GLib/Gtk+ main loop (or iterate the default GLib main - context yourself regularly) and attach some kind of watch to the - bus. This way the GLib main loop will check the bus for new - messages and notify you whenever there are messages. - - - Typically you would use gst_bus_add_watch () - or gst_bus_add_signal_watch () in this case. - - - To use a bus, attach a message handler to the bus of a pipeline - using gst_bus_add_watch (). This handler will - be called whenever the pipeline emits a message to the bus. In this - handler, check the signal type (see next section) and do something - accordingly. The return value of the handler should be TRUE to - keep the handler attached to the bus, return FALSE to remove it. - - - - - Check for messages on the bus yourself. This can be done using - gst_bus_peek () and/or - gst_bus_poll (). - - - - - -#include <gst/gst.h> - -static GMainLoop *loop; - -static gboolean -my_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data) -{ - g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR: { - GError *err; - gchar *debug; - - gst_message_parse_error (message, &err, &debug); - g_print ("Error: %s\n", err->message); - g_error_free (err); - g_free (debug); - - g_main_loop_quit (loop); - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - g_main_loop_quit (loop); - break; - default: - /* unhandled message */ - break; - } - - /* we want to be notified again the next time there is a message - * on the bus, so returning TRUE (FALSE means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstElement *pipeline; - GstBus *bus; - guint bus_watch_id; - - /* init */ - gst_init (&argc, &argv); - - /* create pipeline, add handler */ - pipeline = gst_pipeline_new ("my_pipeline"); - - /* adds a watch for new message on our pipeline's message bus to - * the default GLib main context, which is the main context that our - * GLib main loop is attached to below - */ - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL); - gst_object_unref (bus); - -[..] - - /* create a mainloop that runs/iterates the default GLib main context - * (context NULL), in other words: makes the context check if anything - * it watches for has happened. When a message has been posted on the - * bus, the default main context will automatically call our - * my_bus_callback() function to notify us of that message. - * The main loop will be run until someone calls g_main_loop_quit() - */ - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - - /* clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - g_source_remove (bus_watch_id); - g_main_loop_unref (loop); - - return 0; -} - - - - It is important to know that the handler will be called in the thread - context of the mainloop. This means that the interaction between the - pipeline and application over the bus is - asynchronous, and thus not suited for some - real-time purposes, such as cross-fading between audio tracks, doing - (theoretically) gapless playback or video effects. All such things - should be done in the pipeline context, which is easiest by writing - a &GStreamer; plug-in. It is very useful for its primary purpose, - though: passing messages from pipeline to application. - The advantage of this approach is that all the threading that - &GStreamer; does internally is hidden from the application and the - application developer does not have to worry about thread issues at - all. - - - Note that if you're using the default GLib mainloop integration, you - can, instead of attaching a watch, connect to the message - signal on the bus. This way you don't have to - switch() - on all possible message types; just connect to the interesting signals - in form of message::<type>, where <type> - is a specific message type (see the next section for an explanation of - message types). - - - The above snippet could then also be written as: - - -GstBus *bus; - -[..] - -bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline); -gst_bus_add_signal_watch (bus); -g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL); -g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL); - -[..] - - - If you aren't using GLib mainloop, the asynchronous message signals won't - be available by default. You can however install a custom sync handler - that wakes up the custom mainloop and that uses - gst_bus_async_signal_func () to emit the signals. - (see also documentation for details) - - - - - Message types - - &GStreamer; has a few pre-defined message types that can be passed - over the bus. The messages are extensible, however. Plug-ins can - define additional messages, and applications can decide to either - have specific code for those or ignore them. All applications are - strongly recommended to at least handle error messages by providing - visual feedback to the user. - - - All messages have a message source, type and timestamp. The message - source can be used to see which element emitted the message. For some - messages, for example, only the ones emitted by the top-level pipeline - will be interesting to most applications (e.g. for state-change - notifications). Below is a list of all messages and a short explanation - of what they do and how to parse message-specific content. - - - - - Error, warning and information notifications: those are used - by elements if a message should be shown to the user about the - state of the pipeline. Error messages are fatal and terminate - the data-passing. The error should be repaired to resume pipeline - activity. Warnings are not fatal, but imply a problem nevertheless. - Information messages are for non-problem notifications. All those - messages contain a GError with the main - error type and message, and optionally a debug string. Both - can be extracted using gst_message_parse_error - (), _parse_warning () and - _parse_info (). Both error and debug strings - should be freed after use. - - - - - End-of-stream notification: this is emitted when the stream has - ended. The state of the pipeline will not change, but further - media handling will stall. Applications can use this to skip to - the next song in their playlist. After end-of-stream, it is also - possible to seek back in the stream. Playback will then continue - automatically. This message has no specific arguments. - - - - - Tags: emitted when metadata was found in the stream. This can be - emitted multiple times for a pipeline (e.g. once for descriptive - metadata such as artist name or song title, and another one for - stream-information, such as samplerate and bitrate). Applications - should cache metadata internally. gst_message_parse_tag - () should be used to parse the taglist, which should - be gst_tag_list_unref ()'ed when no longer - needed. - - - - - State-changes: emitted after a successful state change. - gst_message_parse_state_changed () can be - used to parse the old and new state of this transition. - - - - - Buffering: emitted during caching of network-streams. One can - manually extract the progress (in percent) from the message by - extracting the buffer-percent property from the - structure returned by gst_message_get_structure - (). See also . - - - - - Element messages: these are special messages that are unique to - certain elements and usually represent additional features. The - element's documentation should mention in detail which - element messages a particular element may send. As an example, - the 'qtdemux' QuickTime demuxer element may send a 'redirect' - element message on certain occasions if the stream contains a - redirect instruction. - - - - - Application-specific messages: any information on those can - be extracted by getting the message structure (see above) and - reading its fields. Usually these messages can safely be ignored. - - - Application messages are primarily meant for internal - use in applications in case the application needs to marshal - information from some thread into the main thread. This is - particularly useful when the application is making use of element - signals (as those signals will be emitted in the context of the - streaming thread). - - - - - diff --git a/docs/manual/basics-data.xml b/docs/manual/basics-data.xml deleted file mode 100644 index d8972e057c..0000000000 --- a/docs/manual/basics-data.xml +++ /dev/null @@ -1,101 +0,0 @@ - - Buffers and Events - - The data flowing through a pipeline consists of a combination of - buffers and events. Buffers contain the actual media data. Events - contain control information, such as seeking information and - end-of-stream notifiers. All this will flow through the pipeline - automatically when it's running. This chapter is mostly meant to - explain the concept to you; you don't need to do anything for this. - - - - Buffers - - Buffers contain the data that will flow through the pipeline you have - created. A source element will typically create a new buffer and pass - it through a pad to the next element in the chain. When using the - GStreamer infrastructure to create a media pipeline you will not have - to deal with buffers yourself; the elements will do that for you. - - - A buffer consists, amongst others, of: - - - - - Pointers to memory objects. Memory objects encapsulate a region - in the memory. - - - - - A timestamp for the buffer. - - - - - A refcount that indicates how many elements are using this - buffer. This refcount will be used to destroy the buffer when no - element has a reference to it. - - - - - Buffer flags. - - - - - The simple case is that a buffer is created, memory allocated, data - put in it, and passed to the next element. That element reads the - data, does something (like creating a new buffer and decoding into - it), and unreferences the buffer. This causes the data to be free'ed - and the buffer to be destroyed. A typical video or audio decoder - works like this. - - - There are more complex scenarios, though. Elements can modify buffers - in-place, i.e. without allocating a new one. Elements can also write - to hardware memory (such as from video-capture sources) or memory - allocated from the X-server (using XShm). Buffers can be read-only, - and so on. - - - - - Events - - Events are control particles that are sent both up- and downstream in - a pipeline along with buffers. Downstream events notify fellow elements - of stream states. Possible events include seeking, flushes, - end-of-stream notifications and so on. Upstream events are used both - in application-element interaction as well as element-element interaction - to request changes in stream state, such as seeks. For applications, - only upstream events are important. Downstream events are just - explained to get a more complete picture of the data concept. - - - Since most applications seek in time units, our example below does so - too: - - -static void -seek_to_time (GstElement *element, - guint64 time_ns) -{ - GstEvent *event; - - event = gst_event_new_seek (1.0, GST_FORMAT_TIME, - GST_SEEK_FLAG_NONE, - GST_SEEK_METHOD_SET, time_ns, - GST_SEEK_TYPE_NONE, G_GUINT64_CONSTANT (0)); - gst_element_send_event (element, event); -} - - - The function gst_element_seek () is a shortcut - for this. This is mostly just to show how it all works. - - - diff --git a/docs/manual/basics-elements.xml b/docs/manual/basics-elements.xml deleted file mode 100644 index b3c8634b79..0000000000 --- a/docs/manual/basics-elements.xml +++ /dev/null @@ -1,567 +0,0 @@ - - Elements - - The most important object in &GStreamer; for the application programmer - is the GstElement - object. An element is the basic building block for a media pipeline. All - the different high-level components you will use are derived from - GstElement. Every decoder, encoder, demuxer, video - or audio output is in fact a GstElement - - - - What are elements? - - For the application programmer, elements are best visualized as black - boxes. On the one end, you might put something in, the element does - something with it and something else comes out at the other side. For - a decoder element, for example, you'd put in encoded data, and the - element would output decoded data. In the next chapter (see ), you will learn more about data input and - output in elements, and how you can set that up in your application. - - - - Source elements - - Source elements generate data for use by a pipeline, for example - reading from disk or from a sound card. shows how we will visualise - a source element. We always draw a source pad to the right of - the element. - -
- Visualisation of a source element - - - - - -
- - Source elements do not accept data, they only generate data. You can - see this in the figure because it only has a source pad (on the - right). A source pad can only generate data. - -
- - - Filters, convertors, demuxers, muxers and codecs - - Filters and filter-like elements have both input and outputs pads. - They operate on data that they receive on their input (sink) pads, - and will provide data on their output (source) pads. Examples of - such elements are a volume element (filter), a video scaler - (convertor), an Ogg demuxer or a Vorbis decoder. - - - Filter-like elements can have any number of source or sink pads. A - video demuxer, for example, would have one sink pad and several - (1-N) source pads, one for each elementary stream contained in the - container format. Decoders, on the other hand, will only have one - source and sink pads. - -
- Visualisation of a filter element - - - - - -
- - shows how we will - visualise a filter-like element. This specific element has one source - and one sink element. Sink pads, receiving input data, are depicted - at the left of the element; source pads are still on the right. - -
- Visualisation of a filter element with - more than one output pad - - - - - -
- - shows another - filter-like element, this one having more than one output (source) - pad. An example of one such element could, for example, be an Ogg - demuxer for an Ogg stream containing both audio and video. One - source pad will contain the elementary video stream, another will - contain the elementary audio stream. Demuxers will generally fire - signals when a new pad is created. The application programmer can - then handle the new elementary stream in the signal handler. - -
- - - Sink elements - - Sink elements are end points in a media pipeline. They accept - data but do not produce anything. Disk writing, soundcard playback, - and video output would all be implemented by sink elements. - shows a sink element. - -
- Visualisation of a sink element - - - - - -
-
-
- - - Creating a <classname>GstElement</classname> - - The simplest way to create an element is to use gst_element_factory_make - (). This function takes a factory name and an - element name for the newly created element. The name of the element - is something you can use later on to look up the element in a bin, - for example. The name will also be used in debug output. You can - pass NULL as the name argument to get a unique, - default name. - - - When you don't need the element anymore, you need to unref it using - gst_object_unref - (). This decreases the reference count for the - element by 1. An element has a refcount of 1 when it gets created. - An element gets destroyed completely when the refcount is decreased - to 0. - - - The following example &EXAFOOT; shows how to create an element named - source from the element factory named - fakesrc. It checks if the creation succeeded. - After checking, it unrefs the element. - - - -int -main (int argc, - char *argv[]) -{ - GstElement *element; - - /* init GStreamer */ - gst_init (&argc, &argv); - - /* create element */ - element = gst_element_factory_make ("fakesrc", "source"); - if (!element) { - g_print ("Failed to create element of type 'fakesrc'\n"); - return -1; - } - - gst_object_unref (GST_OBJECT (element)); - - return 0; -} - ]]> - - gst_element_factory_make is actually a shorthand - for a combination of two functions. A GstElement - object is created from a factory. To create the element, you have to - get access to a GstElementFactory - object using a unique factory name. This is done with gst_element_factory_find - (). - - - The following code fragment is used to get a factory that can be used - to create the fakesrc element, a fake data source. - The function gst_element_factory_create - () will use the element factory to create an - element with the given name. - - - -int -main (int argc, - char *argv[]) -{ - GstElementFactory *factory; - GstElement * element; - - /* init GStreamer */ - gst_init (&argc, &argv); - - /* create element, method #2 */ - factory = gst_element_factory_find ("fakesrc"); - if (!factory) { - g_print ("Failed to find factory of type 'fakesrc'\n"); - return -1; - } - element = gst_element_factory_create (factory, "source"); - if (!element) { - g_print ("Failed to create element, even though its factory exists!\n"); - return -1; - } - - gst_object_unref (GST_OBJECT (element)); - - return 0; -} - ]]> - - - - Using an element as a <classname>GObject</classname> - - A GstElement - can have several properties which are implemented using standard - GObject properties. The usual - GObject methods to query, set and get - property values and GParamSpecs are - therefore supported. - - - Every GstElement inherits at least one - property from its parent GstObject: the - "name" property. This is the name you provide to the functions - gst_element_factory_make () or - gst_element_factory_create (). You can get - and set this property using the functions - gst_object_set_name and - gst_object_get_name or use the - GObject property mechanism as shown below. - - - -int -main (int argc, - char *argv[]) -{ - GstElement *element; - gchar *name; - - /* init GStreamer */ - gst_init (&argc, &argv); - - /* create element */ - element = gst_element_factory_make ("fakesrc", "source"); - - /* get name */ - g_object_get (G_OBJECT (element), "name", &name, NULL); - g_print ("The name of the element is '%s'.\n", name); - g_free (name); - - gst_object_unref (GST_OBJECT (element)); - - return 0; -} - ]]> - - Most plugins provide additional properties to provide more information - about their configuration or to configure the element. - gst-inspect is a useful tool to query the properties - of a particular element, it will also use property introspection to give - a short explanation about the function of the property and about the - parameter types and ranges it supports. See - - in the appendix for details about gst-inspect. - - - For more information about GObject - properties we recommend you read the GObject manual and an introduction to - The Glib Object system. - - - A - GstElement also provides various - GObject signals that can be used as a flexible - callback mechanism. Here, too, you can use gst-inspect - to see which signals a specific element supports. Together, signals - and properties are the most basic way in which elements and - applications interact. - - - - - More about element factories - - In the previous section, we briefly introduced the GstElementFactory - object already as a way to create instances of an element. Element - factories, however, are much more than just that. Element factories - are the basic types retrieved from the &GStreamer; registry, they - describe all plugins and elements that &GStreamer; can create. This - means that element factories are useful for automated element - instancing, such as what autopluggers do, and for creating lists - of available elements. - - - - Getting information about an element using a factory - - Tools like gst-inspect will provide some generic - information about an element, such as the person that wrote the - plugin, a descriptive name (and a shortname), a rank and a category. - The category can be used to get the type of the element that can - be created using this element factory. Examples of categories include - Codec/Decoder/Video (video decoder), - Codec/Encoder/Video (video encoder), - Source/Video (a video generator), - Sink/Video (a video output), and all these - exist for audio as well, of course. Then, there's also - Codec/Demuxer and - Codec/Muxer and a whole lot more. - gst-inspect will give a list of all factories, and - gst-inspect <factory-name> will list all - of the above information, and a lot more. - - - -int -main (int argc, - char *argv[]) -{ - GstElementFactory *factory; - - /* init GStreamer */ - gst_init (&argc, &argv); - - /* get factory */ - factory = gst_element_factory_find ("fakesrc"); - if (!factory) { - g_print ("You don't have the 'fakesrc' element installed!\n"); - return -1; - } - - /* display information */ - g_print ("The '%s' element is a member of the category %s.\n" - "Description: %s\n", - gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), - gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS), - gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION)); - - return 0; -} - ]]> - - You can use gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY) - to get a list of all the element factories that &GStreamer; knows - about. - - - - - Finding out what pads an element can contain - - Perhaps the most powerful feature of element factories is that - they contain a full description of the pads that the element - can generate, and the capabilities of those pads (in layman words: - what types of media can stream over those pads), without actually - having to load those plugins into memory. This can be used - to provide a codec selection list for encoders, or it can be used - for autoplugging purposes for media players. All current - &GStreamer;-based media players and autopluggers work this way. - We'll look closer at these features as we learn about - GstPad and GstCaps - in the next chapter: - - - - - - Linking elements - - By linking a source element with zero or more filter-like - elements and finally a sink element, you set up a media - pipeline. Data will flow through the elements. This is the - basic concept of media handling in &GStreamer;. - - - - By linking these three elements, we have created a very simple - chain of elements. The effect of this will be that the output of - the source element (element1) will be used as input - for the filter-like element (element2). The - filter-like element will do something with the data and send the - result to the final sink element (element3). - - - Imagine the above graph as a simple Ogg/Vorbis audio decoder. The - source is a disk source which reads the file from disc. The second - element is a Ogg/Vorbis audio decoder. The sink element is your - soundcard, playing back the decoded audio data. We will use this - simple graph to construct an Ogg/Vorbis player later in this manual. - - - In code, the above graph is written like this: - - -#include <gst/gst.h> - -int -main (int argc, - char *argv[]) -{ - GstElement *pipeline; - GstElement *source, *filter, *sink; - - /* init */ - gst_init (&argc, &argv); - - /* create pipeline */ - pipeline = gst_pipeline_new ("my-pipeline"); - - /* create elements */ - source = gst_element_factory_make ("fakesrc", "source"); - filter = gst_element_factory_make ("identity", "filter"); - sink = gst_element_factory_make ("fakesink", "sink"); - - /* must add elements to pipeline before linking them */ - gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL); - - /* link */ - if (!gst_element_link_many (source, filter, sink, NULL)) { - g_warning ("Failed to link elements!"); - } - -[..] - -} - - - For more specific behaviour, there are also the functions - gst_element_link () and - gst_element_link_pads (). You can also obtain - references to individual pads and link those using various - gst_pad_link_* () functions. See the API - references for more details. - - - Important: you must add elements to a bin or pipeline - before linking them, since adding an element to - a bin will disconnect any already existing links. Also, you cannot - directly link elements that are not in the same bin or pipeline; if - you want to link elements or pads at different hierarchy levels, you - will need to use ghost pads (more about ghost pads later, - see ). - - - - - Element States - - After being created, an element will not actually perform any actions - yet. You need to change elements state to make it do something. - &GStreamer; knows four element states, each with a very specific - meaning. Those four states are: - - - - - GST_STATE_NULL: this is the default state. - No resources are allocated in this state, so, transitioning to it - will free all resources. The element must be in this state when - its refcount reaches 0 and it is freed. - - - - - GST_STATE_READY: in the ready state, an - element has allocated all of its global resources, that is, - resources that can be kept within streams. You can think about - opening devices, allocating buffers and so on. However, the - stream is not opened in this state, so the stream positions is - automatically zero. If a stream was previously opened, it should - be closed in this state, and position, properties and such should - be reset. - - - - - GST_STATE_PAUSED: in this state, an - element has opened the stream, but is not actively processing - it. An element is allowed to modify a stream's position, read - and process data and such to prepare for playback as soon as - state is changed to PLAYING, but it is not - allowed to play the data which would make the clock run. - In summary, PAUSED is the same as PLAYING but without a running - clock. - - - Elements going into the PAUSED state should prepare themselves - for moving over to the PLAYING state as soon as possible. Video - or audio outputs would, for example, wait for data to arrive and - queue it so they can play it right after the state change. Also, - video sinks can already play the first frame (since this does - not affect the clock yet). Autopluggers could use this same - state transition to already plug together a pipeline. Most other - elements, such as codecs or filters, do not need to explicitly - do anything in this state, however. - - - - - GST_STATE_PLAYING: in the PLAYING state, - an element does exactly the same as in the PAUSED state, except - that the clock now runs. - - - - - You can change the state of an element using the function - gst_element_set_state (). If you set an element - to another state, &GStreamer; will internally traverse all intermediate - states. So if you set an element from NULL to PLAYING, &GStreamer; - will internally set the element to READY and PAUSED in between. - - - When moved to GST_STATE_PLAYING, pipelines - will process data automatically. They do not need to be iterated in - any form. Internally, &GStreamer; will start threads that take this - task on to them. &GStreamer; will also take care of switching - messages from the pipeline's thread into the application's own - thread, by using a GstBus. See - for details. - - - When you set a bin or pipeline to a certain target state, it will usually - propagate the state change to all elements within the bin or pipeline - automatically, so it's usually only necessary to set the state of the - top-level pipeline to start up the pipeline or shut it down. However, - when adding elements dynamically to an already-running pipeline, e.g. - from within a "pad-added" signal callback, you - need to set it to the desired target state yourself using - gst_element_set_state () or - gst_element_sync_state_with_parent (). - - -
diff --git a/docs/manual/basics-helloworld.xml b/docs/manual/basics-helloworld.xml deleted file mode 100644 index 9097b203f2..0000000000 --- a/docs/manual/basics-helloworld.xml +++ /dev/null @@ -1,277 +0,0 @@ - - Your first application - - This chapter will summarize everything you've learned in the previous - chapters. It describes all aspects of a simple &GStreamer; application, - including initializing libraries, creating elements, packing elements - together in a pipeline and playing this pipeline. By doing all this, - you will be able to build a simple Ogg/Vorbis audio player. - - - - Hello world - - We're going to create a simple first application, a simple Ogg/Vorbis - command-line audio player. For this, we will use only standard - &GStreamer; components. The player will read a file specified on - the command-line. Let's get started! - - - We've learned, in , that the first thing - to do in your application is to initialize &GStreamer; by calling - gst_init (). Also, make sure that the application - includes gst/gst.h so all function names and - objects are properly defined. Use #include - <gst/gst.h> to do that. - - - Next, you'll want to create the different elements using - gst_element_factory_make (). For an Ogg/Vorbis - audio player, we'll need a source element that reads files from a - disk. &GStreamer; includes this element under the name - filesrc. Next, we'll need something to parse the - file and decode it into raw audio. &GStreamer; has two elements - for this: the first parses Ogg streams into elementary streams (video, - audio) and is called oggdemux. The second is a Vorbis - audio decoder, it's conveniently called vorbisdec. - Since oggdemux creates dynamic pads for each elementary - stream, you'll need to set a pad-added event handler - on the oggdemux element, like you've learned in - , to link the Ogg demuxer and - the Vorbis decoder elements together. At last, we'll also need an - audio output element, we will use autoaudiosink, which - automatically detects your audio device. - - - The last thing left to do is to add all elements into a container - element, a GstPipeline, and wait until - we've played the whole song. We've previously - learned how to add elements to a container bin in , and we've learned about element states - in . We will also attach - a message handler to the pipeline bus so we can retrieve errors - and detect the end-of-stream. - - - Let's now add all the code together to get our very first audio - player: - - - -#include <gst/gst.h> -#include <glib.h> - - -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 *error; - - gst_message_parse_error (msg, &error, &debug); - g_free (debug); - - g_printerr ("Error: %s\n", error->message); - g_error_free (error); - - g_main_loop_quit (loop); - break; - } - default: - break; - } - - return TRUE; -} - - -static void -on_pad_added (GstElement *element, - GstPad *pad, - gpointer data) -{ - GstPad *sinkpad; - GstElement *decoder = (GstElement *) data; - - /* We can now link this pad with the vorbis-decoder sink pad */ - g_print ("Dynamic pad created, linking demuxer/decoder\n"); - - sinkpad = gst_element_get_static_pad (decoder, "sink"); - - gst_pad_link (pad, sinkpad); - - gst_object_unref (sinkpad); -} - - - -int -main (int argc, - char *argv[]) -{ - GMainLoop *loop; - - GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink; - GstBus *bus; - guint bus_watch_id; - - /* Initialisation */ - gst_init (&argc, &argv); - - loop = g_main_loop_new (NULL, FALSE); - - - /* Check input arguments */ - if (argc != 2) { - g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]); - return -1; - } - - - /* Create gstreamer elements */ - pipeline = gst_pipeline_new ("audio-player"); - source = gst_element_factory_make ("filesrc", "file-source"); - demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer"); - decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder"); - conv = gst_element_factory_make ("audioconvert", "converter"); - sink = gst_element_factory_make ("autoaudiosink", "audio-output"); - - if (!pipeline || !source || !demuxer || !decoder || !conv || !sink) { - g_printerr ("One element could not be created. Exiting.\n"); - return -1; - } - - /* Set up the pipeline */ - - /* we set the input filename to the source element */ - g_object_set (G_OBJECT (source), "location", argv[1], NULL); - - /* we add a message handler */ - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); - gst_object_unref (bus); - - /* we add all elements into the pipeline */ - /* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */ - gst_bin_add_many (GST_BIN (pipeline), - source, demuxer, decoder, conv, sink, NULL); - - /* we link the elements together */ - /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */ - gst_element_link (source, demuxer); - gst_element_link_many (decoder, conv, sink, NULL); - g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder); - - /* note that the demuxer will be linked to the decoder dynamically. - The reason is that Ogg may contain various streams (for example - audio and video). The source pad(s) will be created at run time, - by the demuxer when it detects the amount and nature of streams. - Therefore we connect a callback function which will be executed - when the "pad-added" is emitted.*/ - - - /* Set the pipeline to "playing" state*/ - g_print ("Now playing: %s\n", argv[1]); - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - - /* Iterate */ - g_print ("Running...\n"); - g_main_loop_run (loop); - - - /* Out of the main loop, clean up nicely */ - g_print ("Returned, stopping playback\n"); - gst_element_set_state (pipeline, GST_STATE_NULL); - - g_print ("Deleting pipeline\n"); - gst_object_unref (GST_OBJECT (pipeline)); - g_source_remove (bus_watch_id); - g_main_loop_unref (loop); - - return 0; -} - - - - We now have created a complete pipeline. We can visualise the - pipeline as follows: - - -
- The "hello world" pipeline - - - - - -
- -
- - - Compiling and Running helloworld.c - - To compile the helloworld example, use: gcc -Wall - helloworld.c -o helloworld - $(pkg-config --cflags --libs gstreamer-&GST_API_VERSION;). - &GStreamer; makes use of pkg-config to get compiler - and linker flags needed to compile this application. - - - If you're running a non-standard installation (ie. you've installed - GStreamer from source yourself instead of using pre-built packages), - make sure the PKG_CONFIG_PATH environment variable - is set to the correct location ($libdir/pkgconfig). - - - In the unlikely case that you are using an uninstalled GStreamer - setup (ie. gst-uninstalled), you will need to use libtool to build the - hello world program, like this: libtool --mode=link gcc -Wall - helloworld.c -o helloworld - $(pkg-config --cflags --libs gstreamer-&GST_API_VERSION;). - - - You can run this example application with ./helloworld - file.ogg. Substitute file.ogg - with your favourite Ogg/Vorbis file. - - - - - Conclusion - - This concludes our first example. As you see, setting up a pipeline - is very low-level but powerful. You will see later in this manual how - you can create a more powerful media player with even less effort - using higher-level interfaces. We will discuss all that in . We will first, however, go more in-depth - into more advanced &GStreamer; internals. - - - It should be clear from the example that we can very easily replace - the filesrc element with some other element that - reads data from a network, or some other data source element that - is better integrated with your desktop environment. Also, you can - use other decoders and parsers/demuxers to support other media types. You - can use another audio sink if you're not running Linux, but Mac OS X, - Windows or FreeBSD, or you can instead use a filesink to write audio - files to disk instead of playing them back. By using an audio card - source, you can even do audio capture instead of playback. All this - shows the reusability of &GStreamer; elements, which is its greatest - advantage. - - -
diff --git a/docs/manual/basics-init.xml b/docs/manual/basics-init.xml deleted file mode 100644 index 3a71be6871..0000000000 --- a/docs/manual/basics-init.xml +++ /dev/null @@ -1,129 +0,0 @@ - - Initializing &GStreamer; - - When writing a &GStreamer; application, you can simply include - gst/gst.h to get access to the library - functions. Besides that, you will also need to initialize the - &GStreamer; library. - - - - Simple initialization - - Before the &GStreamer; libraries can be used, - gst_init has to be called from the main - application. This call will perform the necessary initialization - of the library as well as parse the &GStreamer;-specific command - line options. - - - A typical program &EXAFOOT; would have code to initialize - &GStreamer; that looks like this: - - - Initializing GStreamer - - -#include <stdio.h> -#include <gst/gst.h> - -int -main (int argc, - char *argv[]) -{ - const gchar *nano_str; - guint major, minor, micro, nano; - - gst_init (&argc, &argv); - - gst_version (&major, &minor, &micro, &nano); - - if (nano == 1) - nano_str = "(CVS)"; - else if (nano == 2) - nano_str = "(Prerelease)"; - else - nano_str = ""; - - printf ("This program is linked against GStreamer %d.%d.%d %s\n", - major, minor, micro, nano_str); - - return 0; -} - - - - - Use the GST_VERSION_MAJOR, - GST_VERSION_MINOR and GST_VERSION_MICRO - macros to get the &GStreamer; version you are building against, or - use the function gst_version to get the version - your application is linked against. &GStreamer; currently uses a - scheme where versions with the same major and minor versions are - API-/ and ABI-compatible. - - - It is also possible to call the gst_init function - with two NULL arguments, in which case no command line - options will be parsed by GStreamer. - - - - - The GOption interface - - You can also use a GOption table to initialize your own parameters as - shown in the next example: - - - Initialisation using the GOption interface - - -#include <gst/gst.h> - -int -main (int argc, - char *argv[]) -{ - gboolean silent = FALSE; - gchar *savefile = NULL; - GOptionContext *ctx; - GError *err = NULL; - GOptionEntry entries[] = { - { "silent", 's', 0, G_OPTION_ARG_NONE, &silent, - "do not output status information", NULL }, - { "output", 'o', 0, G_OPTION_ARG_STRING, &savefile, - "save xml representation of pipeline to FILE and exit", "FILE" }, - { NULL } - }; - - ctx = g_option_context_new ("- Your application"); - g_option_context_add_main_entries (ctx, entries, NULL); - g_option_context_add_group (ctx, gst_init_get_option_group ()); - if (!g_option_context_parse (ctx, &argc, &argv, &err)) { - g_print ("Failed to initialize: %s\n", err->message); - g_clear_error (&err); - g_option_context_free (ctx); - return 1; - } - g_option_context_free (ctx); - - printf ("Run me with --help to see the Application options appended.\n"); - - return 0; -} - - - - - As shown in this fragment, you can use a GOption table to define your application-specific - command line options, and pass this table to the GLib initialization - function along with the option group returned from the - function gst_init_get_option_group. Your - application options will be parsed in addition to the standard - GStreamer options. - - - diff --git a/docs/manual/basics-pads.xml b/docs/manual/basics-pads.xml deleted file mode 100644 index edca390644..0000000000 --- a/docs/manual/basics-pads.xml +++ /dev/null @@ -1,686 +0,0 @@ - - Pads and capabilities - - As we have seen in , the pads are - the element's interface to the outside world. Data streams from one - element's source pad to another element's sink pad. The specific - type of media that the element can handle will be exposed by the - pad's capabilities. We will talk more on capabilities later in this - chapter (see ). - - - - Pads - - A pad type is defined by two properties: its direction and its - availability. As we've mentioned before, &GStreamer; defines two - pad directions: source pads and sink pads. This terminology is - defined from the view of within the element: elements receive data - on their sink pads and generate data on their source pads. - Schematically, sink pads are drawn on the left side of an element, - whereas source pads are drawn on the right side of an element. In - such graphs, data flows from left to right. - - - In reality, there is no objection to data flowing from a - source pad to the sink pad of an element upstream (to the - left of this element in drawings). Data will, however, always - flow from a source pad of one element to the sink pad of - another. - - - - - - Pad directions are very simple compared to pad availability. A pad - can have any of three availabilities: always, sometimes and on - request. The meaning of those three types is exactly as it says: - always pads always exist, sometimes pad exist only in certain - cases (and can disappear randomly), and on-request pads appear - only if explicitly requested by applications. - - - - Dynamic (or sometimes) pads - - Some elements might not have all of their pads when the element is - created. This can happen, for example, with an Ogg demuxer element. - The element will read the Ogg stream and create dynamic pads for - each contained elementary stream (vorbis, theora) when it detects - such a stream in the Ogg stream. Likewise, it will delete the pad - when the stream ends. This principle is very useful for demuxer - elements, for example. - - - Running gst-inspect oggdemux will show - that the element has only one pad: a sink pad called 'sink'. The - other pads are dormant. You can see this in the pad - template because there is an Exists: Sometimes - property. Depending on the type of Ogg file you play, the pads will - be created. We will see that this is very important when you are - going to create dynamic pipelines. You can attach a signal handler - to an element to inform you when the element has created a new pad - from one of its sometimes pad templates. The - following piece of code is an example of how to do this: - - -#include <gst/gst.h> - -static void -cb_new_pad (GstElement *element, - GstPad *pad, - gpointer data) -{ - gchar *name; - - name = gst_pad_get_name (pad); - g_print ("A new pad %s was created\n", name); - g_free (name); - - /* here, you would setup a new pad link for the newly created pad */ -[..] - -} - -int -main (int argc, - char *argv[]) -{ - GstElement *pipeline, *source, *demux; - GMainLoop *loop; - - /* init */ - gst_init (&argc, &argv); - - /* create elements */ - pipeline = gst_pipeline_new ("my_pipeline"); - source = gst_element_factory_make ("filesrc", "source"); - g_object_set (source, "location", argv[1], NULL); - demux = gst_element_factory_make ("oggdemux", "demuxer"); - - /* you would normally check that the elements were created properly */ - - /* put together a pipeline */ - gst_bin_add_many (GST_BIN (pipeline), source, demux, NULL); - gst_element_link_pads (source, "src", demux, "sink"); - - /* listen for newly created pads */ - g_signal_connect (demux, "pad-added", G_CALLBACK (cb_new_pad), NULL); - - /* start the pipeline */ - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - -[..] - -} - - - It is not uncommon to add elements to the pipeline only from within - the "pad-added" callback. If you do this, don't - forget to set the state of the newly-added elements to the target - state of the pipeline using - gst_element_set_state () or - gst_element_sync_state_with_parent (). - - - - - Request pads - - An element can also have request pads. These pads are not created - automatically but are only created on demand. This is very useful - for multiplexers, aggregators and tee elements. Aggregators are - elements that merge the content of several input streams together - into one output stream. Tee elements are the reverse: they are - elements that have one input stream and copy this stream to each - of their output pads, which are created on request. Whenever an - application needs another copy of the stream, it can simply request - a new output pad from the tee element. - - - The following piece of code shows how you can request a new output - pad from a tee element: - - -static void -some_function (GstElement *tee) -{ - GstPad * pad; - gchar *name; - - pad = gst_element_get_request_pad (tee, "src%d"); - name = gst_pad_get_name (pad); - g_print ("A new pad %s was created\n", name); - g_free (name); - - /* here, you would link the pad */ -[..] - - /* and, after doing that, free our reference */ - gst_object_unref (GST_OBJECT (pad)); -} - - - The gst_element_get_request_pad () method - can be used to get a pad from the element based on the name of - the pad template. It is also possible to request a pad that is - compatible with another pad template. This is very useful if - you want to link an element to a multiplexer element and you - need to request a pad that is compatible. The method - gst_element_get_compatible_pad () can be - used to request a compatible pad, as shown in the next example. - It will request a compatible pad from an Ogg multiplexer from - any input. - - -static void -link_to_multiplexer (GstPad *tolink_pad, - GstElement *mux) -{ - GstPad *pad; - gchar *srcname, *sinkname; - - srcname = gst_pad_get_name (tolink_pad); - pad = gst_element_get_compatible_pad (mux, tolink_pad); - gst_pad_link (tolinkpad, pad); - sinkname = gst_pad_get_name (pad); - gst_object_unref (GST_OBJECT (pad)); - - g_print ("A new pad %s was created and linked to %s\n", sinkname, srcname); - g_free (sinkname); - g_free (srcname); -} - - - - - - Capabilities of a pad - - Since the pads play a very important role in how the element is - viewed by the outside world, a mechanism is implemented to describe - the data that can flow or currently flows through the pad by using - capabilities. Here, we will briefly describe what capabilities are - and how to use them, enough to get an understanding of the concept. - For an in-depth look into capabilities and a list of all capabilities - defined in &GStreamer;, see the Plugin - Writers Guide. - - - Capabilities are attached to pad templates and to pads. For pad - templates, it will describe the types of media that may stream - over a pad created from this template. For pads, it can either - be a list of possible caps (usually a copy of the pad template's - capabilities), in which case the pad is not yet negotiated, or it - is the type of media that currently streams over this pad, in - which case the pad has been negotiated already. - - - - Dissecting capabilities - - A pad's capabilities are described in a GstCaps - object. Internally, a GstCaps - will contain one or more GstStructure - that will describe one media type. A negotiated pad will have - capabilities set that contain exactly one - structure. Also, this structure will contain only - fixed values. These constraints are not - true for unnegotiated pads or pad templates. - - - As an example, below is a dump of the capabilities of the - vorbisdec element, which you will get by running - gst-inspect vorbisdec. You will see two pads: - a source and a sink pad. Both of these pads are always available, - and both have capabilities attached to them. The sink pad will - accept vorbis-encoded audio data, with the media type - audio/x-vorbis. The source pad will be used - to send raw (decoded) audio samples to the next element, with - a raw audio media type (in this case, - audio/x-raw). The source pad will also - contain properties for the audio samplerate and the amount of - channels, plus some more that you don't need to worry about - for now. - - - -Pad Templates: - SRC template: 'src' - Availability: Always - Capabilities: - audio/x-raw - format: F32LE - rate: [ 1, 2147483647 ] - channels: [ 1, 256 ] - - SINK template: 'sink' - Availability: Always - Capabilities: - audio/x-vorbis - - - - - Properties and values - - Properties are used to describe extra information for - capabilities. A property consists of a key (a string) and - a value. There are different possible value types that can be used: - - - - - Basic types, this can be pretty much any - GType registered with Glib. Those - properties indicate a specific, non-dynamic value for this - property. Examples include: - - - - - An integer value (G_TYPE_INT): - the property has this exact value. - - - - - A boolean value (G_TYPE_BOOLEAN): - the property is either TRUE or FALSE. - - - - - A float value (G_TYPE_FLOAT): - the property has this exact floating point value. - - - - - A string value (G_TYPE_STRING): - the property contains a UTF-8 string. - - - - - A fraction value (GST_TYPE_FRACTION): - contains a fraction expressed by an integer numerator and - denominator. - - - - - - - Range types are GTypes registered by - &GStreamer; to indicate a range of possible values. They are - used for indicating allowed audio samplerate values or - supported video sizes. The two types defined in &GStreamer; - are: - - - - - An integer range value - (GST_TYPE_INT_RANGE): the property - denotes a range of possible integers, with a lower and an - upper boundary. The vorbisdec element, for - example, has a rate property that can be between 8000 and - 50000. - - - - - A float range value - (GST_TYPE_FLOAT_RANGE): the property - denotes a range of possible floating point values, with a - lower and an upper boundary. - - - - - A fraction range value - (GST_TYPE_FRACTION_RANGE): the property - denotes a range of possible fraction values, with a - lower and an upper boundary. - - - - - - - A list value (GST_TYPE_LIST): the - property can take any value from a list of basic values - given in this list. - - - Example: caps that express that either - a sample rate of 44100 Hz and a sample rate of 48000 Hz - is supported would use a list of integer values, with - one value being 44100 and one value being 48000. - - - - - An array value (GST_TYPE_ARRAY): the - property is an array of values. Each value in the array is a - full value on its own, too. All values in the array should be - of the same elementary type. This means that an array can - contain any combination of integers, lists of integers, integer - ranges together, and the same for floats or strings, but it can - not contain both floats and ints at the same time. - - - Example: for audio where there are more than two channels involved - the channel layout needs to be specified (for one and two channel - audio the channel layout is implicit unless stated otherwise in the - caps). So the channel layout would be an array of integer enum - values where each enum value represents a loudspeaker position. - Unlike a GST_TYPE_LIST, the values in an - array will be interpreted as a whole. - - - - - - - - What capabilities are used for - - Capabilities (short: caps) describe the type of data that is streamed - between two pads, or that one pad (template) supports. This makes them - very useful for various purposes: - - - - - Autoplugging: automatically finding elements to link to a - pad based on its capabilities. All autopluggers use this - method. - - - - - Compatibility detection: when two pads are linked, &GStreamer; - can verify if the two pads are talking about the same media - type. The process of linking two pads and checking if they - are compatible is called caps negotiation. - - - - - Metadata: by reading the capabilities from a pad, applications - can provide information about the type of media that is being - streamed over the pad, which is information about the stream - that is currently being played back. - - - - - Filtering: an application can use capabilities to limit the - possible media types that can stream between two pads to a - specific subset of their supported stream types. An application - can, for example, use filtered caps to set a - specific (fixed or non-fixed) video size that should stream - between two pads. You will see an example of filtered caps - later in this manual, in . - You can do caps filtering by inserting a capsfilter element into - your pipeline and setting its caps property. Caps - filters are often placed after converter elements like audioconvert, - audioresample, videoconvert or videoscale to force those - converters to convert data to a specific output format at a - certain point in a stream. - - - - - - Using capabilities for metadata - - A pad can have a set (i.e. one or more) of capabilities attached - to it. Capabilities (GstCaps) are represented - as an array of one or more GstStructures, and - each GstStructure is an array of fields where - each field consists of a field name string (e.g. "width") and a - typed value (e.g. G_TYPE_INT or - GST_TYPE_INT_RANGE). - - - Note that there is a distinct difference between the - possible capabilities of a pad (ie. usually what - you find as caps of pad templates as they are shown in gst-inspect), - the allowed caps of a pad (can be the same as - the pad's template caps or a subset of them, depending on the possible - caps of the peer pad) and lastly negotiated caps - (these describe the exact format of a stream or buffer and contain - exactly one structure and have no variable bits like ranges or lists, - ie. they are fixed caps). - - - You can get values of properties in a set of capabilities - by querying individual properties of one structure. You can get - a structure from a caps using - gst_caps_get_structure () and the number of - structures in a GstCaps using - gst_caps_get_size (). - - - Caps are called simple caps when they contain - only one structure, and fixed caps when they - contain only one structure and have no variable field types (like - ranges or lists of possible values). Two other special types of caps - are ANY caps and empty caps. - - - Here is an example of how to extract the width and height from - a set of fixed video caps: - -static void -read_video_props (GstCaps *caps) -{ - gint width, height; - const GstStructure *str; - - g_return_if_fail (gst_caps_is_fixed (caps)); - - str = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (str, "width", &width) || - !gst_structure_get_int (str, "height", &height)) { - g_print ("No width/height available\n"); - return; - } - - g_print ("The video size of this set of capabilities is %dx%d\n", - width, height); -} - - - - - - Creating capabilities for filtering - - While capabilities are mainly used inside a plugin to describe the - media type of the pads, the application programmer often also has - to have basic understanding of capabilities in order to interface - with the plugins, especially when using filtered caps. When you're - using filtered caps or fixation, you're limiting the allowed types of - media that can stream between two pads to a subset of their supported - media types. You do this using a capsfilter - element in your pipeline. In order to do this, you also need to - create your own GstCaps. The easiest way to - do this is by using the convenience function - gst_caps_new_simple (): - - - -static gboolean -link_elements_with_filter (GstElement *element1, GstElement *element2) -{ - gboolean link_ok; - GstCaps *caps; - - caps = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, "I420", - "width", G_TYPE_INT, 384, - "height", G_TYPE_INT, 288, - "framerate", GST_TYPE_FRACTION, 25, 1, - NULL); - - link_ok = gst_element_link_filtered (element1, element2, caps); - gst_caps_unref (caps); - - if (!link_ok) { - g_warning ("Failed to link element1 and element2!"); - } - - return link_ok; -} - - This will force the data flow between those two elements to - a certain video format, width, height and framerate (or the linking - will fail if that cannot be achieved in the context of the elements - involved). Keep in mind that when you use - gst_element_link_filtered () it will automatically create - a capsfilter element for you and insert it into - your bin or pipeline between the two elements you want to connect (this - is important if you ever want to disconnect those elements because then - you will have to disconnect both elements from the capsfilter instead). - - - In some cases, you will want to create a more elaborate set of - capabilities to filter a link between two pads. Then, this function - is too simplistic and you'll want to use the method - gst_caps_new_full (): - - -static gboolean -link_elements_with_filter (GstElement *element1, GstElement *element2) -{ - gboolean link_ok; - GstCaps *caps; - - caps = gst_caps_new_full ( - gst_structure_new ("video/x-raw", - "width", G_TYPE_INT, 384, - "height", G_TYPE_INT, 288, - "framerate", GST_TYPE_FRACTION, 25, 1, - NULL), - gst_structure_new ("video/x-bayer", - "width", G_TYPE_INT, 384, - "height", G_TYPE_INT, 288, - "framerate", GST_TYPE_FRACTION, 25, 1, - NULL), - NULL); - - link_ok = gst_element_link_filtered (element1, element2, caps); - gst_caps_unref (caps); - - if (!link_ok) { - g_warning ("Failed to link element1 and element2!"); - } - - return link_ok; -} - - - See the API references for the full API of - GstStructure - and GstCaps. - - - - - - Ghost pads - - You can see from how a bin - has no pads of its own. This is where "ghost pads" come into play. - -
- Visualisation of a <ulink type="http" - url="&URLAPI;GstBin.html"><classname>GstBin</classname></ulink> - element without ghost pads - - - - - -
- - A ghost pad is a pad from some element in the bin that can be - accessed directly from the bin as well. Compare it to a symbolic - link in UNIX filesystems. Using ghost pads on bins, the bin also - has a pad and can transparently be used as an element in other - parts of your code. - - -
- Visualisation of a <ulink type="http" - url="&URLAPI;GstBin.html"><classname>GstBin</classname></ulink> - element with a ghost pad - - - - - -
- - is a representation of a - ghost pad. The sink pad of element one is now also a pad of the bin. - Because ghost pads look and work like any other pads, they can be added - to any type of elements, not just to a GstBin, - just like ordinary pads. - - - A ghostpad is created using the function - gst_ghost_pad_new (): - - -#include <gst/gst.h> - -int -main (int argc, - char *argv[]) -{ - GstElement *bin, *sink; - GstPad *pad; - - /* init */ - gst_init (&argc, &argv); - - /* create element, add to bin */ - sink = gst_element_factory_make ("fakesink", "sink"); - bin = gst_bin_new ("mybin"); - gst_bin_add (GST_BIN (bin), sink); - - /* add ghostpad */ - pad = gst_element_get_static_pad (sink, "sink"); - gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad)); - gst_object_unref (GST_OBJECT (pad)); - -[..] - -} - - - In the above example, the bin now also has a pad: the pad called - sink of the given element. The bin can, from here - on, be used as a substitute for the sink element. You could, for - example, link another element to the bin. - -
-
diff --git a/docs/manual/basics-plugins.xml b/docs/manual/basics-plugins.xml deleted file mode 100644 index 0d263e1ee8..0000000000 --- a/docs/manual/basics-plugins.xml +++ /dev/null @@ -1,85 +0,0 @@ - - Plugins - - - A plugin is a shared library that contains at least one of the following - items: - - - - - - one or more element factories - - - - - one or more type definitions - - - - - one or more auto-pluggers - - - - - exported symbols for use in other plugins - - - - - - All plugins should implement one function, plugin_init, - that creates all the element factories and registers all the type - definitions contained in the plugin. - Without this function, a plugin cannot be registered. - - - The plugins are maintained in the plugin system. Optionally, the - type definitions and the element factories can be saved into an XML - representation so that the plugin system does not have to load all - available plugins in order to know their definition. - - - - The basic plugin structure has the following fields: - - -typedef struct _GstPlugin GstPlugin; - -struct _GstPlugin { - gchar *name; /* name of the plugin */ - gchar *longname; /* long name of plugin */ - gchar *filename; /* filename it came from */ - - GList *types; /* list of types provided */ - gint numtypes; - GList *elements; /* list of elements provided */ - gint numelements; - GList *autopluggers; /* list of autopluggers provided */ - gint numautopluggers; - - gboolean loaded; /* if the plugin is in memory */ -}; - - - - You can query a GList of available plugins with the - function gst_registry_pool_plugin_list as this example - shows: - - - GList *plugins; - - plugins = gst_registry_pool_plugin_list (); - - while (plugins) { - GstPlugin *plugin = (GstPlugin *)plugins->data; - - g_print ("plugin: %s\n", gst_plugin_get_name (plugin)); - - plugins = g_list_next (plugins); - } - - diff --git a/docs/manual/bin-element-ghost.png b/docs/manual/bin-element-ghost.png deleted file mode 100644 index 5ca55dcf44de61d6ec42b92d17a9e04b48860d33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8532 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 EUz^0+4gdfE diff --git a/docs/manual/bin-element-noghost.png b/docs/manual/bin-element-noghost.png deleted file mode 100644 index 61dcb65e5e9477bade43e796ac37eed163e5b789..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7934 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 J$1A`L?$E!`n44N`&vN_Pk-EuBM&z|h@t51;j{ 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�kw!#PSDmQhkKmV~vteU%8@bk$!juLFPfP2o1qI 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 PKtU=BujIeVS%m&Cdg2L1 diff --git a/docs/manual/clocks.png b/docs/manual/clocks.png deleted file mode 100644 index a96de4e2297f2edb6e8d395e14c9fe8a7c34e662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65406 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

VQ=zP)&BU8QZ}zaEVq<@A}*Hp=x-L$-kD~Z zu(Q^ih@P}Q`&JuHvoP8so~XpHpg-%Uclf8#;Y+TOP1b)5g0Cj)F@QpfmPUtO z6jv&lHw;&#$GTi6x%vQB6c%C82;2JlAgdr}=rC(v=PslD<}O`zVeCKORs-JxUb*W0 zN|SJR#ZtL%<_%+j@07}TtnQc3yR*6#n{VRxsjx(xw8Z%oynJkQX@?)X==G42*Vw0J zRvD7xm}}JF>7frPXQa@Hr_~Z7LhU?DeCcm-R&J$S2-6NEBlHpFCLlO;pwTOLCdk7H zokkch7uLUA2oIOvd}Gg|OILbgwvv<@;JlgMTb3v5>XWUY%DV*c9iP>--Bw=xIAKO2 z*PDnl!F~58)lM6JYCmWDb*XLs<7Oo|4KCtS0zbbJQqu?)#Rqh#X2B_DxrUp6n5X9> zyln$3_?hKO5@l#5hO5oITuV|-#&ri#uS5y-^y;#?Nz~~o?7yt6_D7|Bo~Fwu$?RZ)?I)$qMs5Q9xpEjqz9ICHqvG3h7(5$ zf$M4$#wv5wF66(9zeSC&`aXcPQriDR?t|i#I~( z&VlDPsBTLy%G&(tZ&P@%{Oxj2M~+%ke!uPqkgdrl^E3_Sx-&gNPxml1j>IKzOQ~j?qX}#3wMoYqN&;(r*oY& zX}vX$oEK;BDnsu>PlCpWC||)#(E}?V%4Ohoe?PpSkf!b_1pjzW;P9t$6#=n9{63@@ zm26**A3Guni`!44Ed{N7@W}1axkV*v0)%1NceOV^ z+?kxPlURB>a41?^wLY@&j(_ZJ`m4lFuM>JG$!ya2)b=nvf_W)y=kYkXfm>cfvuR5& z#SkL9eX4U=X`L(#N!J4i4lbMP<($VNFA;ou^6ZVI@PXB8ef3-+eLPFQ;xZN)TLMAp zPog5W_w&|635oi;7c@O*k%sKv^i`9ulM)v(+Z8QP^MJ*q$wgQZ3i9$qvNUhzvT~lW zl1IYulQ|KpBqFRK>R4PB7m{Qd@%IZL{3;e8X+$W&)0szHTs9{V!a| z%<$wUJjf&g#j$Sh`Q|fA@IF=%TS72|yHnG^!@E(mffL+$i=0pEE(tW<2uXhOyFUY8z%M<6gTaRj}T>^~h{giFHG0RjB z4?3F;)ann^&Mirb(;uP1$i^$Q+o;KlVs|>}qb_2B=w4hWw+876Y_0ZkZ$$=nSPqTM zd^4{ar6OJ=sTzD3rZM`aGa@NmXpZ=BDwa!F2ak-c=h8eX-jd!Lwi{gGhUJP4d9PJad!+i<2hzJjCE-ivKGdscroJ0fEP2kPbIX~)1Z;0)Qmfv!nKKsp+ zLDTGg(E|=}d!J%p_zEx+a5NP*Whsh0Y8PuH-CxQ%PQBhQ0_|dpECP=J zEzXqyy@wGUv9~~%>e$(|J|{=89s&r#f5Adn*D&c-w;Kf;t0BJk&-s@okriVQ z%S{ORikD}D_npgi#d4iMUZDs=d*zDzYFY18N=w%e3aa^?)nUlh>-k})Y3^u!z*t+9 zyUcaE!h$_b|Bma4^H3BOf%wqgN+C*UOEFW8-VdM&@PKGTv?e#7H^GBsQfvk4o&m5@ z($I`*PZ%qF<<0%qzE%$0&O>#qXT2kBXtY75+I(FY)c1nN8%i$sh>f0os1_XXc{E8U zV1YhIv>c;D3$lF0v=u)pD9jG1+{j<1x{^wI&X0^(>7gS0fLRqry?DA8Tac0TQ8b;_ zACP=M_bsW7YRWd-hRfRLb%0fb~fA2t#$9ws=hZJ z5}w>?G)X~!I1qWk51zkZ>s3?PLSx^;A(Qz#E$i$rNNmB#-PzGL z63{UML!rYv$|{VE`5j#FmFlR2V`Yl3)O|J0&oWNU}}`Q+;Sxmzs)Cuqg)f$ zwC6veQdYao?h=gI3UONbcZD}^YYJq-A!ss>P;lmT=)8|7DcRm@Q0f`a{VD8>QGR+u`mn3=UT$UfDJu=waG zq`UmlBY7IT__&13)B1m7e}w^@9}wEaMXu2Kfb=4(?D{`VlzF`3Nc|2PV-{)aA4fy+ zpg#)Xu^0BKvhSTS^!0pSGPkv)!85)y<I;E=DVSQpJzNNCKUEYeDo{i#mg5Es0tPUy3I+plpV7fil;y6!M`q+mje7t z;L5pMqj1DFDaofV+UO`Un{I|R0JkfRT^`X{b5;j`^=Z_a0;ik5Q*q}z>`$(5)G(i7 zKdGOQK(A&)0ieBG#b5ZfpLyZW#$E^_S4MR1ZhbLdpfv2*1KK6{b-Tphqn!U})Nw?o zX55hZ9O&z*dAfl?0A4$xI%~;ZEXIMkuI~%N7c&t8&b^l1$AbUO1*lnayH03{7rRdq zA9r|L$9Cb^BP2KYGNAX|wc&WSULKHqQ}&+z{JEx6y~*IE*hg)tk@%atEmjz=7gbUU zne>m_(mOq#5UqCKwdn53TvPKMZ2RSx<#{=7b`vC6FOEK@2d}=dH_3%bTvo4NG=iC4 zja}t%|C774!cWMa(r@M+eZBbtL~fu|^P{aCW6#6MOR744#2oVFvm;REO??E;rv%mC zTUMjW+kQy3Pnv2G25*kvqs(6)KMHYM%f4v3-He%R%7!Us-eH$1X~WUc&g0uZ!VcVQ z0V})!2V?E!{hKM8;PFv=@8I&n-9m^CF4U0-2+NwXbN(|Nn$M2)>EH40*Ng+n4Sbh6 zV~cjzH#X`Yf#6nlZO1pS^P}8o_R9^<0G){*yX#O5YJnJI`gvX}1lhEuA}H%^6oI^0 zV=6#mx7#3>LW)93eS&#sDqvvxM@s5y)`U!0)u!#zE(e)c*uoJuD~a#lrQAp;m?%93 zdpEV&Ay&@t3@;MTDtC*n{(79emKBTZOpQ%^il%7o^Zp1Ww^~Rl|E{x80BGLp<1KmG zUS5YsbEMFM_f|`e#_F7iiLg9E3=uC6@!mu6-Xcu)x$;rF>z^aTG76&x!_)V9974@# zNgvJjo|eseX7SZ+KA~CdhSE2ED+qYI$W>3=(i>KyEEb2^maz1~Xqyz{$p%vD`2Aae zVv~Vqd=~1K6c_+6P(a`ROGzN~<>g9MJVR3_+=>#1XNR`TwK(Q;j^?y(16De=3R(a+ zU`9pxm!j7G;ICZG6%i11GGU(|2$Rw(vb3=2i2l?XOk7_M`4mCxjojbaN*byB`&XjU zgP5%}K3b=3Ha}l=PR&z}#n_lnTl?z`r5ySKUJ)pVb>W9WiN5))LZG(SzM8duo^ zEO;J{V1ra|%_dBhTiNUCuPtDx3oY4x+kFTx)k!~ivLbh7Egg77GdNT9vrcSmCf3@D zT5Ul$c{o6Rzx4_F=m~#$@w8q>-tP@5q;_FeP0`6SmmJ=*)~kB$OSeyrS2{2C@dRE+GcsVhRC|BgN?xFJ@c}D^H{hrOjL4@Nxh*_Q zmKIxDSgURikf$Rf93u^+mWX&C=Q^5cRAj|uMhc4xzrqk$3n?Y0qwd+z;|F4PG{HM_ zfL3htgItd7nJtMg@mG?2frHj#>8C5NRtQ1~~cVQMVFbt@{uFFW%<)C34sVKTJU85++d)Qv8@H@bui`^Op6`^QNxViC1B;H>AHCyVC3Y> z%#W;AgNEF$KunyDW^y~n7|mFAhzF*tgvILpx|}bg;kCK00Mb-q8{eN4A1wx#?(FaM zNI<~rKPvJ`63{kCro>DWAV&TV?yD-yfDg!a65*N`!_BL$5_kXIC^UcXpkS@(9hfT8fW&6iRrX}=%AtK2yg9# zic0HkN}6J7RufI@V@?LcMFCuO^`lxVrkg8du=}Ms?o5ajs#3j_*JMGQp&+Pt`6 zhF(0oSg7^wezz(`PRM7^`~|Lep67jxSBio0WpPRHl?Pw#y5To$0+y4)B9Kh7NOH&b z`vc_cS^A@NpcK)YS7a_O5!aV&b4BW(;-Y-yKRhw$3?#Na>^8knjk!cr-DGl~u738^ z_N*7(btZa5Y|E`(pMN0=TC7>)L~#+#u; zAbjLD-R;Nzp3)V7PX7*{+_>^y}6<0edel0ud)A}m)DIY*grUamqVmFYF}`H_DZ=+ti5U>BiG`MI-S+UbB|-x#NL@M zNgO#S>O)dnoZlyk1{3C|h^HcC#}pZA%C$zSbSB60yI}2>Yx{eP_gwQ%dGFU_joFxs z^BGx#^!0AV0?KHVELNt&kOCQ3*~t9zrURsBa1Q=Q0M_-nZS-AVZ0ygz?WN?keT;+A zR%I;jyy(X2e{}|6LTllZL1k=XOwoiEkz=b&?A4G1wxA^1kJ-+sO(d+OzV5ts zrcRsMjRT}Er7Lv~w`HMC>RK8`Vr6AD`D`zUj2;AZ7Fq2@b3}5L?g%XJUvq-grF9im z42a5*?&&rjUW21A#3!fAI0$My`#zdVb`ri0QQrllFX?u4lhuMP9?sfWu||9ZH76$t zV$RR>Gs#nlz{;z&z!$?qU9Y*Km|AZFfQQRg^Ro-Hze#7X@Zim-(#hT3Nqp4)SE#jx z23``p(dRF));15?q}L z`+|9fReffom+j1FVs&5t(-zBZ-({zr$RE)-@k%z74lX&?D~bnL*C-oat}+rElA-dCQ_M=iYqi?()oeS_-d z%)yB8q1ikMsI^qb4iD!k1fdOz7)qAtBUS%w-8ogG;#E`z4o5VT&y0PL7EJW{(ku26sg=O8+%|j86QWXR3#+TgloaB6$q*gUt7i$lNuoP2}qdutK2#>yn#2!m!u=??3rL45w!>Pxlq zt3!$P2FB}0EwbkU1uH*Yc~JeITFrmW{NV*N+S47HO?)5f4mGzOe*MMEtBBL6;)(sm zCe7`sdeeMOwt!&rYP%m>O>~W?;2NYy|4T_eZRi>zq9iA0fPz~502F?Qypy@!AdX>C zVm2Ggnrw;at4MLk12UwP%H05`Jc%8NmuvKBCKtNMcZmtpgmp5*2eY3R>;?-5kO$lU?&4GGl zy7gGt!Xy6SG_o2>_`&qvGIny0^r6pD2jJE}&&gJl()*U0lGk&X2ab>0UiByOM^>_X zDCcVED!D1)(IVzQU>8jCOU%KYxS&d|xHYtAA_$t-3R!kze|V`P8an2sHj&YRNf&>3x?gF{Hf|2zB-^X@K z>VlxBsS3jkV+t(p5S%d#43WI9_zYkeL5@T;>{I~?3DHSI8U1zbgX z_rDwA!GGGmD-lyPo4jg8Tm4;4@)kT-*!3#2lfqq=+7!r6aEjX; zzI{@6|9DO6Kh%NX1LKB*s5Hl}~){F}Yobm(BfO<-4LyOi15|>&X)4=?Lf*)*s zY$I)(igl-IKYh?`YyakV-f&L1L+Lhu7?*5J(6PwM`=af@z0S3ntBqu^k@ys zXuo{ya@sp(E9&+(+93>`<`b>?a&)wJeJ9x9m$xoXRW*s02Bn(vXca|rS|P!2&sF%7 zU4Oq^Z1Z*Zb(?9W+^{sEVYH8>B9Fb|7C77)V0WIV$0aY%mR?0l8ZBh}C^Z28*-or- z8p)5omC>#oSWARsByyzio9b-2s!(f@D|shT0AUq>fao)iG!o;RY&3Tnt@(&jD6Y6W zRPcN&mD%f>ds9jZl%tgV?($?OZgbPX&V|*rFDka0S;d8t0{4)z!$ok#&S`zBp3<6z zQyBNn%nhI-V^5A8H5=-F`fELAmDYj+5d;9;JX^u1EqC?!6q6$7X7B^%s-YACS$O^Y zAu@@=^gFBlvK?J=p5huujb4r^A;6=4G}UqJYcvEpiU!+?wgzGs=+bfH0Y%zD95r5N4{1H zD)9bXCKsE3ZpQKF+_+?f{2;^+x9IXpyBI(-_r-q#q!T{ zR%vE?)P<(!&gyb|1rl;T)>{<$zcp?V^)Ng=y4SY5>2H&-1e67I3DV(s-zNz5Dj1$> zQ5P0Wxs?CU_8EO)zkjlW8SwUCGf@~#@ih$X@q86`eKbL-{(<(J@s>F84?g+xel=I6APLLteyWE{zLAa;cs#PC= zg!^>b5p#Lbv_aI(4hczufN-3HoJF15`RmF`h&o@xFX1%W5y3$&TmVO#6O)D{N-udm z=iy+Aq`jKxXM67K{Cu1JOp8wcHp6l@b|3y>L@>Z$jG-@(?<3y9VPPZEFJ{8tnO>mF z_Yb>5>JHp?M3!93`e!V6++6Tw;|EfHb#hHUoIDMq4^EF|GXK1IcKmn-vF0C176l{# zpOiA%)lz{yW(~ zX_XSVhJ@K2g)l-5?&18>uw2aOYf`lYpjdTO>uHA0depE+% z{ZQm11sWK%@;vJNDwbLiAiZ+!PYJW>`YP%|zcO3S6pRy_NK6JFyrZL&Yb4vgrKc7= zn^TA_gX)epeo8#_A$4V>;~w&dph9cT!T5 z(FbAZe~tG)^;u(xCVfB>evLs=~cq8udx?^2stCf zB~yX41QKF5mUWU}8<)PQhD4wM!rq>FiVa*x*vJ}R5YVnYR$5Wj8SVb}@-6DDeJj0R zDI&)`&pZ;$*cB<3o(e<+eg(eQu}1nYy5ir7f;@N#xIEtkI$Tm4|4N0oLbCe?I1Fvp zqd%3Z?<=n_e`lIih@JjuFr_vEW;a+a)VbcS@*mQ!jt8C9Ohc-R5`WywQaY@Zbnsfs(qG^=Nt{*R*c&P&!KBplYN zQx)*GzOkYFisse>RDR_n+M;IaR{ahj)JLHLi9=}}*>*JR;+Y&GMcjRJhug@xl#TaO zEXT%tSCezrrBjh>p2vI76fWH`KjQfTg;dIy(IR9eOE7^}@XkZ|X{7L`{>Jq>!sKr5 zrFfv}z2}@SunRtYddRs@A6bvNjiQ(QwYv4SySsb+Ttk>#^;)!G+_J}1(o*{o5Fg4Y z9|E!i;j@X(@5?+Gp2a>WN*BLx3yYBC+ZUjM8zPf8Dntw-!W)(5gPVH_Q9&``s zR;GVryo&1sDu*=6doIK?q3({?%BI(tryGY47r`D}CqWYaIrsmR_*2nfCnrlF?|PU*mMfLbFzsIb8t+ z0kGbRh0!b~XV9jk9k^H6y%^G~NmUe%wRNhPD3ub3jA;C0=e?QW>a9&757cV?qz<&* zdo2poHi2fz`I5QJUyLp}QR-%(mQ^Re=dWDEH;!>$t-$6k6x$Y*SIQMJIp+rYr*^ZCMy<)YD27H76rcPNFFX5V_hz>B{Pgy(L1 zqRypUimn&27r2PY5W0Of??iI4#G@nDe4jXt*RY>L z7eP0|(HMK-G>8A5V5ft;YPw>3)nM7{NK@KFo*xeDm8t-WV0g=2*xu85O@s7z%cu_z z?Y9eC_Cd1_2VCeKxT(FbFv*-}{yZ{bFEr5O6neymkTE=h<86?U*nLdgQsp$N1|L4u zyQ$9b3YLC|cVe)ys&ukDTdk4|2;K43Z_yl@k*6ZFksl?5gmn`;H7-0aJE@!z%1nJL zq3z_gTSsCgFQ+ma%-C8vSA6pu*=9~`^o)xK`4F)D?gccB4OI0ZXvPN*`N7;Ap=bFe z8|@Y3$KAy>z%A^Fts}^?I^GQ&8b~IlPV6{)e5(&#CoEQbY?T`5FcYK;xb0BWn`9di z=qN+)C`6+ne0w>y(~DnQ1_rTDB*-ga5EJxs9$(XTlU1U(CCM8V3a)3au9kOpZ z!sY@f@l#S$ddiQ#zh&m32!E?)9kIQZ%4x8cB9LG+uWVrVLb>^d4OFMS)U1T(B}%Qd zw-e4F4#q;&-bEtDf8h9mEv3w&_;UwAELeBJBr$+bPMTG9W4Yu#9jz4o+4gvXnV zt*%R5E5E!x4qGoXxTq-pO8RVVs|dV0o2UIUBHQGnh6U)n0kW8ZD!TQN#JpJb4@3Ji zsEv6HT7Z_{Guz%&-a4LA-rHIH{S*@5Xxw}2Xzg*U#lc`l*AG~n6XIA6Ad0(&DMUoK zJ}6H=46CBFpfP3{UT!-tBLfP^lG?pAdF{4@SVpw>T%#VXhL@2YcMmx^S}jG1rDwas zin=|8O?eyf(_Cpzp{%zfGva0W(t#|F=95w6;wdhR>(;PV&7s~&^@$cK0bqA~0L5tS z=1lcWx|LH2h>C#+oe!?D9n9yLzXS9`r)(od$)%0{N)ROz>LqoUm(6v7uW0B7BBq) z8GP77=XJMyx%f(M5RRP5Ik5yzdgK%GS`LUbzyh3v^Yd*)=qUrdC`LBss9)0RRXY;^ zcX*PW=ZO!wct$UvKyq{(DKI^1HnzJL>S6xKa@zFDr<)%*TR9inVKyTyvn!!?ot(Cw zOEitb$#wbcunFt&>flF^j*VPTL5p;lrj~Pl`OV+a^x;=-*ClgC+hq3JLApROBsow` z8%_7@aHUiP;X8)hvRczaj^-L*LakeCv7bFN4)gl@D3E7gG;yv$3e{?Qm+Eic zQEx#0=U4Z|?r)&RcDz#d;T^?Pph03SWDsG5fI0<0Ok%{3!z+(MGNn_8djQew8>u?8 z1WG6Ek9k+hfrO9u_y`4{K6|v~$|842@b>$m$rcIE?xC#Za&i}7JPyuISAV&9Z>FyB2@Vv`Hf8$#g5K!paaWgkH1?dk zH=yg*fScF7`dG{03ohE=?N#oJ+)i5p)ot8=JJhZ#EwLk8Pvvv#`S%O2c{2cuaHM#J zVKy%C9SHw@$GQ-h$Hyxa4uz+4pl)SL2Bul?UGh~3i0 z-+RAHe|OiwcQt2p)pQyQ3VbF$%Kd$a!~FCqj;u`jNwNY|92b{T=ALhx(dvcQxPl47 zi)GOP=`iXwBB*6QXxkvN=(Nea(syVM!H+*`y6zX^OnMd7i^#xh8t)O+b?weXHs_<=%(8=F zdmeKmD)Q^~*J_rtu*NyU{JPPE>+cQy9owUeLHz}=b%&~;hp!Jt)TtY+N6c`A@Q|K0 z(H5qWTk7h{SgVT_lxYqNgDqCC>gLZqckmI7hcqjnGP(Ue)x+zMjtw>r+5X@}N)KM{;XNCL44B!ZrV9!AQMxpB{G>mwKi9TV&g=fVjj$L+ zoidQA|2am?q`K~b)wvlbg;P~^?eL2DNbUO@XwS%;H*Tp%*8&2?Hu~!li3z`E6_)yM zdqZ&^Js?S#I=qctuF1|vcXtX`8YN^r*isx^A8CcY zw~{EbdA(qxzRlyH!lD_T;uVkQ*(j7KjZEv8nrspcg9Mzc?XI-;hTwT5i5Y-a6%7%; zza9~8rl@X_k+pgXS46XbIuzWOZ@)6ljL@f&b;T;b+i-i2+`2n!lFLPt%;2f}@-<_sg-Q6k615|sb-e+C;ubj|3sRs=AGv6C z?XJU8l3Bsfo7?O%64&nCoWB02-m}NHHM7^` zbnVDvsQL_yX;CHOq~iC+SS zIk$AR4lujM(u|=nOe+yyjs(5yeO_l$Rqk_&46@v3QWLCV_Z~cY0Yh}WpdQ{px%P1s zZ@@p^T$|LJTh~NGv(D@m5cVjz@GH{Mv|oOdsZ-b`n%%DnnnoWGH@g^P(@WIMrNybf zw!JbY_RReFTz~!Gl{2yg;T#q_PkRvWq?km_kxnNfdKlRd?^$yB4YT+Mt|E==)q%8T*y2lx4nP1N2ut+W*{cDy8!dmw!F z`O=*e<7Y=WNp-4dx7iqv$-$3?PTs4YqfRx^&iSPRQ{%2G!%t@>{p03SA{VKG+IRn> zxwi_7qido@i699Cx1hl#!QF!dcMa|mY;cz(xChsu!Gk-4W`Kd)-tT|T z?YTVX4!Wmz&#qmyYVE4k(@-oYe#5q_{!u?m8v$QtwQ^1S(W=$r?~;?8(jmUEv2F{a za<#i&dY_!}APw1Y%q`e7xY>F6bJ-A!{bI{#Y7*gbIb`Eo-GWFFRhb#fZTYt?M5~%JOkdzWIBG&IFZW!u zi@#6k6;XH`Dv`zaDNt5)ADxYj*;{&F<^7ESKGuIoDg!L8IZE-hk_V@=7YQZng1onT z0o#h8(QD*rQkN1XEXv&nBQQdn5-2#v4l^li!|at0F^PPBq8Nf-xY<0t45j$o(UMy~ z1CnolYyIXO^;Fk)BFD8%t(FhNtg8*9v#!T;7};$I>fgMmNaHwLB#`Kf^@Cr_4_^8#~_FegudhNSCyL*+|_ z%}f&qi?GZ;?&r}`P32x@a_JVT;}Yg0rlBuNrkRD0D|Kp|T7=j*G|C^$9UA9UOYwIb z9vybAcj8P;z)?o_7HEP;r8%EIkqL!7XU*UZ25IlOY_!#UxHTp6$E6|W?egWaX%HB* z)eH{Vy%!}SckEfHL{^2%5ld@QRhOLsmX@?XlHWTzz$K1k3=K~2~ys;Gjt9~&sjpS0uDsT+U16?uAH8A&%&^wfv!Lf@mmXWPG?duSPD=O-UcDg=eCA;gD4amFe zkSQpR7!78Hn8^bTzPJ9vesX4Pv?ObJl;=$TB?4!TTsag=(d=Ti04sPumOU|hJyOy= z$+0Pn1^m~q{rB?8{wCIFz~IHJ7eEvXpB^@~-OcgX@Yqh^(tN2Ccq?)}r*J8C;yyk_ z)%JMfe-Ar0`xSnq>avDQv$o|U7Gw=H+BH8~v z84+}=D*m<9vb^O|2aL|eKta-0G5bX@%V^fhv$oDej0Ov%hlRNuvS>lI^%3@lZ%;RH z?vd~K;>mZ{o#as2I(6kq(NjK^4Gd)Tl*&=-H7u}AgO9Iy*?xxZd~dG`Kn`hdY8oj9gEuK<^1AfxX`6Hix zEJ?X`!FKH)a=xFVCsmfKhtXSn3GGwbiHn!1Q5+4a!DXIr#{K{9EFItZGZD=e<|J6TlO@ zQQO9s$re}}>Hr=*^J=4ek?C@!HWf3yC76(mGm51jIj5ngprJroHEOJ)Q9gVk^5kbt z$C{dn>L?N?w&=o&S)5tCa>?4`I&;d6Qq+4s0kxaUHeQQzfQ+bjqKBbj4mhtxQ)K;_ zd@_`i`_#TNyi@%w!r~%gdzh`3X;DW;$sc{Rqm!h-=zuhAilBIK7*2UFt6@h9jx4*r z20LVN@j?)r5*m=_HVJ$cMA-y9884Lxjc(jnDzt?% zT?eo22UPw68+#%}h4e6TBFgz*!qMTPhFtmdNEDFMmL1PSf6cL5W%2w#bj%Me9QAe# z5S~Yt&u6dr>R^j%5MPpTs^`yFn^OYT`BN(hkg)a@ypd)bym1^Vzt&9#0P{8pW=}gq z9t8$~eL*Scd?dlDL0~RRzpts>6}*Tj+<9YpaLn0Z(18br^d`99{9e@Tx10=fziCkz zA(huMIwIoq+htCWnkdfosYmz$K8(#vz4B1-`Z7~KEgcn_p@H<<3#g=)0qUIR) zBkbTnE)#ayLAE$y+;a*%dbn+6;x}ZaxEb{X_L44H%6y43SC*T(7TmT3qYrDikB`VNk%amlqvfQSh%T`toj15KJ#=#(& z@H&9e4GA%zrw#^{8rDAcvyJSOdTO5!fy;qymeW$!ICn$iO?xp-+>%Jt%F`WbW%Ehr zZi6kW2#7ccR-ss;$?SF8;Vpc1tL}I=$Pi3&*)fq@eEic_V&&mBs;~O77`O8F!Pka| z*-DwDr{!qj3~_M&`FewO+5b?_IDIs+Gad2<%fJ6R&;Q>}=BeY!?D6py*U^8|+}OS* zp6dRf0UO%6;=sr!$dDq8LVoVmdERa~dtlJGX2K5~~ae7-AQ#4v9o9yx*kfE#3hzv3 zAlB-UDtT)1-|0XvtR|SGMOu8|qeo?xbl^mPfC0ZZcIU&+^C@P!7n5c!&c~k#ADUrJ zN8>^2X@a~zS03!1ZB54rKXnxvV(yFJF$G-qq-KM(Pu5%Rc3j4%Bt@9?;mpnJ9f%gI z8Af0`pGC1$3fnM!`nCr*qfs)f6+PySNg zrXTpE0g456SWkzK8CKL1Z#w327V7E+N_hG3Y^TW8>gWZnJ^9nG;Y4Zd^;nd`0ZO@$ zJyl0F9@oGJ%+yihk)WTnSWdfXnCRnpKA#Ow*A6imc9yPQHyMh4%iMOq@9zLmm_Ycl(xL8(V3#3KVlrl7p;)>2w#N6*1~nD*pPu1u8NFx>Mgy_ILC z|L96pZBo`Etp?)S0^N8}UMn&en`JYq%d}p3`qs;~61%jP-`Jg5;NG)n(S3B46~FTY z@vnA5SLp=rhqtxS1hM&&fFbU-zS~&p%=iI8N^x5cGD2shZW*jHhITx*>g#bJ%|`74 z`lBv`0dgQz40&yxZx8m%h$! zY$+$Syc0bw8@H5`k8yMy69-cw0a?uWZtr#Xqs18b__cUw4{ zBq%U)l{)w5FO(SnBH^N{<4iGld14bp-YvxXj->{Ekbw5P;3rWW9fMkV($e4LE?)z( zQ4DVR!u&xm{MWHQi=IH_xZm9139yB07+BHtq|26T!8c~w??G#X_#c5?!Se0FbO4ck zyY}!ON)Pz$&O88?|LDRj*y`^GRtYq!?+L(knGFa(2oca~V6W3ED21=Kh#5?5`PSYt zoSsXj=H!P5V@rf59<-f32mnfO5ko?T?W7Sa8sI1zRq(Dr!Vo&uzrS&Q(WVpqJA_Rw zE62(9-)X5I2^L2G4oQT+qZ?@Z?+R>j`2_F(uAus!L<|4#3W=9Ya@!&Qokmmt|LcJ6 zxi7GxYyeZ7;kC|%@H;A}q9esIbbTWWip-$bcKm?hM$BMgvhq2>4Dy^@Iu4dp7e^Q+ zGG>~E-2}tKKLQv4?!{4Vpe;Ak8O}G%0;t2hma>L|J}?xOaw@3`JNHWyNUVC~;K2*> zK4*>cWJQvBqCyFrT~#Tp9~Ppr{y<6K>GtIB$FOl4`S+yH$t8-1l(g|*BOf#p)j9e) z=RyRifZfuzm@8f$RVxtf=0JRPn^&>DaU&MVFRK(7qjD?jHIvCxt!Ampa`4{zhPe|A zV2R&t6=`?`+AB9kk!^5;xA67-pMSTo-PeCXE|Ge!V2k8+enjvrcC%;6?Tr7pWBc%9 z7?sagTDZ6^sO9a~=x1McFT2yTS_~aMwvM}PU0(vx&BLt^poG+?Pe0Pgh<2S~^}TiJ zwr}Y(SQ;mp)7hBIU%V5cAqY~VT(yZc9*Om{k6pe?s^~R?Y@A`^yp?v5mjEUMr2KM@ zOwtm&>MZR6Kj#pH&lq1j78O+}l8o!UizlIpXDeXlRDj+gVGz#|RVb4Jqs0yGnIS4A zBC$4csITQXDK~Ggl<0-2`4t$*Fj2uSh?j!V=C~9%^4qx=AH$p%^)mFolz?6X3#VkO zhpRT;tuGi~Mx2tmco%@0C@E!ZC}6D)4I{K>)iN&q?{Gx}~3l!-nPJD5?Q z=@@?6Ok!f>&Pc>>!DguJ(}n2AfX=KSncS@;rS8+X<&j(8c2Qf~D^T+(S0DH9yeIBy zL3|xb-vz&csZZ9+s>|7#lo+UdsFW%Gg=aodotCERLoZQUDr>Jp!@9koDr=!;g3|z9 zi3C{3=&OYIz6hckaS{kM(vNCyBs|C#Ipj)519XAGc2&Je$2}p(SL1v zENi?F)(z{mdNoy_#o;L|CDGFPRzvTuCKSf$UY>l_!D$PqzwhVTw*G9bD^p&atnCS{ zTU10(m(JX|F4~ON>8%^B8AZ5e7RS7{MkW|}U0X39TqcqJmNRih>LHY>l?vK`MWu}V zKNG3?2y<5&4nAUu^{!&vdHDXwRPz2 z2o%d6U1pHudWMjLWnvq>P9@>7#V7OUpb3%qMsn$#`iI|nUGT3`*>hz1kOUho?wYdC zxmV3sbUg#K|FHYw`LH~B0U_%zZx}E0asa79fGBG@L0rLxJMmOr-bD+-h&w(W+R&Nb z`AA^x4;9II9fOi=6qjc#mf+Zt?x#WROL-k$zp;>r4P~|6YB_A(A?4NQgM;9mx|X`1 z>cHt%hSZ9WDkeF}BnB>MV-x>nhYQNNIQ(YmAv@ngSv%Q zFKY)ay2^L8xL?14OYCs4xlz2SL|Jz5OXVY3$(_+vXsFBZ^A#0Z@L*RI`>hZ2&wE5J zGo0Qf@cE-@iZT0U$8)^XT)H14y<7Svx!iW|+qL-ARMpSgP>0kQ>%S!dB}p<>Q2cx_ z{_AkgFJJ2Uom=nU4-tHoFT9w^2MbZoE#N3AVhl7bN}RJanJ_Wt?r+3>S!jDZm@QJj zy^YJcIcL4#G&QXTcB0xZVN`^KB|2SBr-jO6{n~w?*2G!FbH_qRElK9J|47|8UJvTS z@+v!KT2=_C(udu~-H2J(a5W39J62+Lw!+@`zaGy7EH#3rA&oG9JpZ`}-+T^~F@gWK zw!O{YCQt;*Z^%YZC1RVt3k>9{a2R1-5o!aybnqa$As`Pg>3l3BR*g(&cx#>S?cvRJXegPF=|Zq&rU*Y=`+e48B+h!O>x zI2zrt+RWG3RhF<=;>riToH6Ggl?mIIjp0x?Sd#ZIZy!WNa>WTN;EKLRrj;fkP9afV zX~wR%Jz0y#b)e;#_$pp*<|LnXa=EL@qU-;sU-9*);=QG?iHoy`h#2m1+XfAdmB06v z0*j|(42s|*t?VbKH(J{%8o1DsfOrEjmYBKf0%NI40iopi0z4IQO>4rC=eX1t7z%HS zjs3z;=9FSNe~?*ztWx7(6u@Yo5!y2UB{%p()HI-qT)9xw>1c{um;$g1PA^Zz5P7PU zOVYEiE_KOld`XBygevo^Onw|CzC`a3J*Df-foFzC?lyY-vnmQS9O{8nh(~*M%Iz2h zL1eXvD||0dYiMC;A_eHYA+bmH1=F~+8wp+dKwj`}oBwwlDiV}pFIYrgqK8W@adMwy zU=bhfInu1MoaIbOLCy{;eR^|%9*O^kgtE9M^_=Wz+i8pS$VXrz+m3<)$#k#1!bxiJ6NPhDNO!Krg(6t4++2#g5BfUFhs4Njyu<5(?fC{k-8@ z(J?RYUzbcIW(4(JaipVK=uv|AaoV}iOFu*~2F@r~IcSp$|?n?K=9g3t#U-8+_ zX)k^}?x2@=Lo%_UWKkHZ;n-L!+KKs7dSKeRI2%wzInlRgh;m2^QWr5a z9)Ds;v=4u8-#H}z^O=5ZmP-~7T0c#EyMW3qXL0B!{VUYl_ZQ6a zA>VssMbzk7l(ZSPtllf9X7Z&T^=_Y19005NCq|E%^f#>(u}vMg#P;x-KQ3;pV78>h z)}~;X%I;&<9>D**^3ab%?*&sHH9yr&@6Ey}tfo$HZaFTk0FK6<Fmk z!oC;R$xt-B4g3tT_GQoPuDbIl5t4@2VUtfiJ1#98e0uDBdS0g?z4w<5meJ%1Llvpf zLT1y$<~*h*+&aqpl7@9}eoB8T=s>vl-zWp-9k<_5dP58yv;3ePU+ODQgv{yg7Y>&Q$5Rl`Zh1#IDhNtc-nM z^RqoG#hq{}?_FM_?Nn*At5qPdW=3~L3*7_1)R~FXEX;It@z9$zRcGxHmt8M*x#b%P zX6wG_is&^Y=oa9Xf*RoG>muBr$)wySlt(mQuX++$xc5gCG!U~*XA21uk4}3g(w9*e3fnTpGMxN$(ONCje(g2un!#-U z*z9wp2KfPC&<~4kIY~A&of*?PbtuvrUhmSI<}fdRO!N4%{Q|J{_utZ@;k7@%X35;& z>08&65TvSz-PCqGK%WduN?DHET@w zJ|iCiw3ykMKD#W6RcZ4r*Dw82tLFYrJc9F!e`l0{s{Ye((d(9vS4hd~-5E;_ex2=+ zzhp%^Geo}1rE_d1`=aLP92R2SV6#%ga7&BeG7&89rxn}54B>6P0)c(y@$OGWZeW^n*vanb~ z*C=wV@unEtF!N3*5vJ2e$N{YZi;gV z`)CnjriS(EzmEf3E$2?2B8*3b<4@xT6ez1KFH_oO+A7tVUh(ZkM7>@s@-|QB62L3y z&Xo0oLyk8Vbd>610s~qy!?E9pWln{a>ec|Jt%V>KelBOCd!j}dw#>^*mIn!#C)m{U zzHMgCl$+vQ=V=-`ZMwGw*$u|WM6HwmJ}Q(t3d&9j3MvoT&CITSw=-)teliDjG~B428v?;Hd|NzpGtn19Uo+y@VBsy+rBv5V@~#T|ZcO}sMn4Z779 zQeo?-87f(;ty51EX50=>_!i`Mlp8eBxGzmgVD)|{PBC|U-NgTK@4*wDJ6U}IA~u*` zIUfq!5UHxS z(LvcjDXsMWmm0wc^jVGS&R)L$QlUjhtdq(Q+p+M;7AtvXfKKFKCQ*bR*Ue?!-yQg^ zLoS;|D6X^{CfrsdCVa~y)mA$nyZADh=Tuc?NiyNUPf(;!;qJ zhJpWXJ36m683#n>oln}+#kyzGVbu;0bzGJg1ID1WiC0V)F>mq!IOa8gF7IpW#d6Zw z$pAYX%6rxCM&+B45&llC!uHJEIlInD600hdp7; z^9GtKIW{z`O=0Iln<)%Im9ode`Wxw`{8oA^WgSg@SHiL^fw5y<^s>@_4ON2 zGPOj1(rpXNpa&%&ZWAO9l@Z_GVnxadIOX9(M}wMZi}Hgu+Ukse@^hx~y2!h;{?gCr zSA6EK%>ee?JU%QO*aUuK2ef&{6+>Iu#cc;HisVaincFdzvObG)^D8?CR{(SF`K43W z`8alCsbDJ7J6)lfR?*?%TF37|sGR8po&Wu8z^YR?Vlp%)b{wpPIRDrwL-*0)E<{oTUU}EFIdz)@i z$RK$>cBeBXD3HlGF7eLmA2cW~DN~sZ(@hHxgdJZ3?e*}z^8ALL^ZX?B`2cv#-x=0!90C>(fwndiTwmpHxV8;Q33 z#i%^C%GEe46quKFaOaY{c&;RNam0viN6@!_lsmCEin8jmT^o=+bPW6j8n#>Qpr#+h zcz=~#p-!e)6;1D?K=_oF)ExBqt_6JE9xcKhOp%n{makOW>mu_W@R~0ZoE6F9Bh{T< z6efcCasF4ySaoXk+V3p3YDaF+i2fLY^2}U{2Sk~#mhc*a`)AE z;-cdy(-+h(9J^SuDJ$0rE7w|ESDb@D=59c025^3{9Io4>9y%${|7z0hUm<(j)1y8E zKIqDPEXt(sc?oL)g5p|)@!Cyx9b@gv%STBFsan8bj!awBpe+WA(BWX5lbgyX^1pHu zdWn{NfXCx$Vh81k4|=a*WmB#;6VT+09+h9)j)LY*Gu~KTRwhzpVgpRNoR!R3{wle> zASwU6()!bcttQZ`wo;<#c|#PlJp$d%Ntg@X1+w(N!Wz(#y?;n$2(*X7DJxAcQ)q}J zG?UN#Y%zRTbob5{ zT?RhW#~u1k6gv~FOZ``cu>MhnbzmBY!DTY`rTMTe&%l2T4cA=a1%5hqv9e@ca^!*} z7fY$;YidOlKql1ed~5>-qnBw6^Yvq9}#JkwRyBrfN|7$e> zy@c$WcRG5ll#)ub8g`f3m8?a52M!q|ne!T|WI$n7UqeG7SCYT<@0FGrFCS3poiqZD zI5h?JZGQ}NQcq6RnwT4NyWqQ0r-(yEi`6xkj~X1`3v&JXdvg5DOqbdVs2BgbrT_F? z^+yw5S9}(KP$h!(EhUca$2?V4o!O6uhE5Do@ut!eF+g>Fyx^8j=Gja4@7_O@Cw*0* z^aYq965{PG@jkBR|0?l$RDysM4k+`>6w>*?#K*HIkYrre>ut4iC3h3{x&*jEi1z@Csg9`$o_`QrRP7+%5@eOL-x z39ex%f?0T+v?AGKKPKO&cLIu5K*uRZAgHv?m%rox z75g#vNo5qJWOE_AYDCH-w4916lCJu>k^)qL{_d}8;@j_5=<7fq1VXeH@8G39(kLgk z)wanAu22M)8*zS^EGK18QLG%68yZ6opnN@5Sjj{CUR>tCPLn3U#5HCbj;Tm8&NoJt zRV`zT8SC)_8;|)YH#LL(1Ixc-fo(MypMVy}Dj;qBWvzcf!il8)|4n14R5{Tb`8ALR zN14#2vve1aUpy74zT}RrWK3S3GhjuiEi?6;oq2T~UFGif9<8okcCpO9aK>#BX$O-d zF%qCwy_z8G8E`%ohW%_D`@#umqENb)UEr@m>7=0YSH5u-K~OzVQU-RcdR}hzZ`QHA z@JY?RN1rTKKL5o3R&qUGVyr|fNwfd*V;0%;HsJ?t->MD@q+fK>&w)A}>8fncUfHjF zim$&M>qC?iZ|3^3fsWEOQ=nMGn+gVspV(o#4W(#b<6q#tAd}mP_F(~r9e7`vSKBBs zwiZ4)RyG`hWMSEZ%AYXuWr{iU7gX)Dwv4WpWG)1!IB$#e3W+_R$QTPLl)|PMwaQrH zf))&syNXo@#2&hP&;X^~TC2y_d77F9viq&A6F~Q-!Y@mOxlmi4)zq>0(IV}eZX(wU za^+OV4zCX$VTm%vkC+OXH2>}_>!?Oh70?*#l$bp@LQ1mh)atf$sMfqhLE+=fFsq zT#X!VJ#F}Kel*F@xcNx8g{p<6(_$d=8XcpMx=XiWh~1NI(KW*#*E+yiQc zZisnjmYilY$5@{G-hwWTZh~Rg{;+S$E#k!a$Q~qwhBb{U$c+;WRDpEnyZW;H{mz$o zffZ6&{!i0XcelKC8zs#}EAp+xNitUwPrQHQTWuK%po}^j zUw7coVx{QZk+`M3Sa#t;s*vvG>I8=mp7`d7wO9Y3Y{chquoryG#8INz4qi6CPzKuR z-oEAOo%X0LpR|6_OP{V*?6}#HMjDHp74BqCgT0O)TMW3}olu2p;G3}W>y`Y9{yBzm zjekx6T_WPN)C8WRc2NYBpDLY*7oflfIh1FS6nLa>|A-xT{DAja0u4Cxbs&L0LU`J4 zZ&2Riv-&7%Hph1^dW+VL9xthUfx*;N2TpSIWdkCnMxwI0?hX|nU3PAuivt4JwZ%0; z1~Mw!Sj>zSmKu(4!H5}?8oAPMyQ0X;w4(26vIl4;+4md1VV1%o{|?&^F`4VA@l-fm z0gLi;mN*VTn>spz`xe~y4>>rZwP~9V%L;f zU65NV(`Z>Iq}y)EW?b2S)@}u;CH*9+qAZN;fuwZwUlM$FHKUVxy&Y!A(Drl5xBTrB zJk@J!^78j`Ezws%=$hpYQD}o-($73;`uw>AI@#l3GPpf2(B1ZF>a~NXa|dWMA(@i*UCukNlBmw$mq0PVYe+paZH|I8=Y6chBwLQvr63sV1Jy#DJL( z>$o^}xr>kEXoIo;#3jw60iC64mO!yt(QB$ZX414ydxq5eE0M;X6U4*gS(DBWjn7+% zbiR(c{=Z6}knm5cpc7WbHNDcNy5!T_+L3>U0R7SwpDxpfe=^W#tI4CaEw|sW=4!!N zwyx-%e)kF#{_dq9a5?YM7ElUwzN8d0S&IXIv8{P_dbdM(-v3?!03kIdf+6F^#DvJ( z#D`)Wz`DqLfY>11$mF2XMZ5hB9ms!9Eh39&O{2hTK$88guX&&sH@;OunQiMNfC~K@ zel+gnRv{iq78D*FHZ0)R*!xH*z46G0YVrC6rRUqERs z(walrcue;}Do(ka+IL5^*7F#$?Sw;^Z*6B3a^g>g!lEI434b8Nv3)1N8_lq6)EyZU z^4TGlB1Qp?s^=^|8{k5_$e1TbBZ^Ugs9$x~hKfqC9(tvr3yTIy%E>CTckQBnAHN$P z-Q{-FluU=+`r^O#+NshxzxuAU2qg~Z)hUt^<0G1+$^ zS$LjZG?`fNxuyoY3HqXIw%k)~#s26jz)Eo!t4jzFvTeEC8S(My+0@JlJ{U;4lD-*s z_}YYFvmUOwp05aOe3oLx0XH1|zlIqh&FN;Nd`bX>O)imTXgvGZJ0PpOfTyVU^iFV^ z9G4M?Djc&hY)4LZZkjyUog5%($w7>)brTW6SCBK)*?(gJgtc+&WC!4wU0EKC!K zbU--_@MT(ZVgp}Q!=Mm{8v@Pg2JE-Mt36gNfC(c3#k`5RiM}5f*ECl-8k#W;!`*XK z0|D?=KxxC@fMR^b?GdK%pA=vW5cAwVKK&U;|JhMx?2=^s+~2EqX*?-j_wAWX8w&7j zg~jdlBl#n%0PCV>(Ae}NAhLOxJ@x-cc9Qa>LH-uWEp%OZ|6wH>Rcuk-eB{#FAB(BH zp<7?4Em| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - Clock time - Running time - - - Stream time - - base time - 10 - - - - - - - - - - - - - - - 20 - - 30 - 40 - 50 - 60 - 70 - 80 - 90 - 100 - 110 - 120 - 130 - 140 - 10 - - - - - - - - - - - - - - - 20 - 30 - 40 - 50 - 60 - 70 - 80 - 90 - 100 - 110 - 120 - 130 - 140 - 150 - 160 - 170 - 180 - 190 - 200 - 210 - 220 - - - - - - - - 10 - - - - - - - - - - - - - - - 20 - 30 - 40 - 50 - 60 - 70 - 80 - 90 - 100 - 60 - 70 - 80 - 90 - - - - - - - - - replay - - - - - - - - - - - - - - - 100 ms stream - - - - diff --git a/docs/manual/diagrams-general.svg b/docs/manual/diagrams-general.svg deleted file mode 100644 index 98c427eb98..0000000000 --- a/docs/manual/diagrams-general.svg +++ /dev/null @@ -1,14982 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - gstreamer diagrams - - - Luc Pionchon - - - June 2008 - This diagram uses icons from the Tango Desktop Project. http://tango.freedesktop.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <Element name> - - - sink - - - - src - - - <Element name> - - - sink - - - <Element name> - - - sink - - - - - - src_01 - - - - - - src_02 - - - - - - src_03 - - - - - - src_01 - - - - - - src_02 - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - - converter - - sink - - src - - audio-output - - sink - - pipeline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MENU - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file-source - - - - - - - - - - - - - - - - - - - - - - - - - - src - - - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - - audio-sink - - sink - - pipeline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - src_02 - - - theora-decoder - - sink - - src - - video-sink - - sink - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Gstreamer pipeline for a basic ogg player - - - - theora-decoder - - sink - - src - - - - - - - - - - - - - Gstreamer "hello world" pipeline diagram - - - - file-source - - - - - - - - - - - - - - - - - Multimedia applications - media player - VoIP & video conferencing - streamingserver - video editor - pipeline architecture - gstreamer tools - 3rd party plugins - - - - - (...) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gst-inspectgst-launchgst-editor... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gstreamer core framework - - file:- http:- rtsp:- ... - - alsa- v4l2- ... - protocols - sources - formats - codecs - filters - - - - - - - - - - - - - - - - - - - media agnosticbase classesmessage busmedia type negotiationplugin systemdata transportsynchronization - - gstreamer plugins - gstreamer includes over 250 plugins - - sinks - - avi- mp4- ogg- ... - - mp3- mpeg4- vorbis- ... - - converters- mixers- effects- ... - - alsa- xvideo- ... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - multimedia applications - media player - VoIP & video conferencing - streamingserver - video editor - pipeline architecture - gstreamer tools - 3rd party plugins - - - - - (...) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gst-inspectgst-launchgst-editor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gstreamer core framework - - file:- http:- rtsp:- ... - - alsa- v4l2- tcp/udp- ... - protocols - sources - formats - codecs - filters - media agnosticbase classesmessage busmedia type negotiationplugin systemdata transportsynchronization - - gstreamer plugins - gstreamer includes over 250 plugins - - sinks - - avi- mp4- ogg- ... - - mp3- mpeg4- vorbis- ... - - converters- mixers- effects- ... - - alsa- xvideo- tcp/udp- ... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - sink - - - audio-output - - sink - - - pipeline - - - - bus - - application - buffers - - messages - - queries - - events - - - - - diff --git a/docs/manual/diagrams-pipelines.svg b/docs/manual/diagrams-pipelines.svg deleted file mode 100644 index 30696ac874..0000000000 --- a/docs/manual/diagrams-pipelines.svg +++ /dev/null @@ -1,12768 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - gstreamer diagrams - - - Luc Pionchon - - - June 2008 - This diagram uses icons from the Tango Desktop Project. http://tango.freedesktop.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MENU - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - R - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - - audio-sink - - sink - - pipeline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - src_02 - - - theora-decoder - - sink - - src - - video-sink - - sink - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Gstreamer pipeline for a basic ogg player - - - - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - - converter - - sink - - src - - audio-output - - sink - - pipeline - - - - - - - - - - - - - - - - - - - - - source element - - src - - Chapter 5. Elements - - - filter - - sink - - src - - - - demuxer - - sink - - video - - audio - - - - sink element - - sink - - - - - source - - src - - - - filter - - sink - - src - - - - sink - - sink - - - - - Chapter 6. Bins - - - - - Element 1 - - src - - - - Element 2 - - sink - - src - - - - Element 3 - - sink - - - - Bin - - Chapter 8. Ghost pads - - - - - sink - - - Element 2 - - sink - - Bin - - - Element 1 - - sink - - src - - - - - - - Element 2 - - sink - - Bin - - - Element 1 - - sink - - src - - - Chapter 10. Hello world - Chapter 16. Threads - Chapter 17. Media types - - - - file-source - - src - - ogg-demuxer - - sink - - src_01 - - vorbis-decoder - - sink - - src - - converter - - sink - - src - - audio-output - - sink - - pipeline - - - - - (any) - application/ogg - audio/x-vorbis - audio/x-vorbis - audio/x-raw,format=F32LE - audio/x-raw,format=F32LE - audio/x-raw,format=S16LE - audio/x-raw,format=S16LE - - - - - - - - - - - - - - - - source - - src - - demuxer - - sink - - src_01 - - queue - - sink - - src - - - - - src_02 - - - queue - - sink - - src - - thread 1 - - - audio decoder - - sink - - src - - audio sink - - sink - - - - video decoder - - sink - - src - - video sink - - sink - - thread 3 - thread 2 - - - - - - - - - parser - - sink - - src - - - - decoder - - sink - - src - - - - audio sink - - sink - - - - - - networkedsource - - src - - - - - queue2 - - sink - - src - - - thread 1 - thread 2 - - - - - - - diff --git a/docs/manual/filter-element-multi.png b/docs/manual/filter-element-multi.png deleted file mode 100644 index dfbbcb1e8110a662ea7759fa862d62ff7226d399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4383 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 diff --git a/docs/manual/filter-element.png b/docs/manual/filter-element.png deleted file mode 100644 index 7e2ea32605a3f4021fdac9c44a0e8014cb3f764c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2718 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 - Playback Components - - - &GStreamer; includes several higher-level components to simplify an - application developer's life. All of the components discussed here (for now) are - targetted at media playback. The idea of each of these components is - to integrate as closely as possible with a &GStreamer; pipeline, but - to hide the complexity of media type detection and several other - rather complex topics that have been discussed in . - - - - We currently recommend people to use either playbin (see ) or decodebin (see ), depending on their needs. - Playbin is the recommended solution for everything related to simple - playback of media that should just work. Decodebin is a more flexible - autoplugger that could be used to add more advanced features, such - as playlist support, crossfading of audio tracks and so on. Its - programming interface is more low-level than that of playbin, though. - - - - Playbin - - - Playbin is an element that can be created using the standard &GStreamer; - API (e.g. gst_element_factory_make ()). The factory - is conveniently called playbin. By being a - GstPipeline (and thus a - GstElement), playbin automatically supports all - of the features of this class, including error handling, tag support, - state handling, getting stream positions, seeking, and so on. - - - - Setting up a playbin pipeline is as simple as creating an instance of - the playbin element, setting a file location using the - uri property on playbin, and then setting the element - to the GST_STATE_PLAYING state (the location has to be a valid - URI, so <protocol>://<location>, e.g. - file:///tmp/my.ogg or http://www.example.org/stream.ogg). Internally, - playbin will set up a pipeline to playback the media location. - - - -#include <gst/gst.h> - -[.. my_bus_callback goes here ..] - -gint -main (gint argc, - gchar *argv[]) -{ - GMainLoop *loop; - GstElement *play; - GstBus *bus; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* make sure we have a URI */ - if (argc != 2) { - g_print ("Usage: %s <URI>\n", argv[0]); - return -1; - } - - /* set up */ - play = gst_element_factory_make ("playbin", "play"); - g_object_set (G_OBJECT (play), "uri", argv[1], NULL); - - bus = gst_pipeline_get_bus (GST_PIPELINE (play)); - gst_bus_add_watch (bus, my_bus_callback, loop); - gst_object_unref (bus); - - gst_element_set_state (play, GST_STATE_PLAYING); - - /* now run */ - g_main_loop_run (loop); - - /* also clean up */ - gst_element_set_state (play, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (play)); - - return 0; -} - - - - Playbin has several features that have been discussed previously: - - - - - Settable video and audio output (using the video-sink - and audio-sink properties). - - - - - Mostly controllable and trackable as a - GstElement, including error handling, eos - handling, tag handling, state handling (through the - GstBus), media position handling and - seeking. - - - - - Buffers network-sources, with buffer fullness notifications being - passed through the GstBus. - - - - - Supports visualizations for audio-only media. - - - - - Supports subtitles, both in the media as well as from separate - files. For separate subtitle files, use the suburi - property. - - - - - Supports stream selection and disabling. If your media has - multiple audio or subtitle tracks, you can dynamically choose - which one to play back, or decide to turn it off altogether - (which is especially useful to turn off subtitles). For each - of those, use the current-text and other related - properties. - - - - - For convenience, it is possible to test playbin on - the commandline, using the command gst-launch-1.0 playbin - uri=file:///path/to/file. - - - - - Decodebin - - - Decodebin is the actual autoplugger backend of playbin, which was - discussed in the previous section. Decodebin will, in short, accept - input from a source that is linked to its sinkpad and will try to - detect the media type contained in the stream, and set up decoder - routines for each of those. It will automatically select decoders. - For each decoded stream, it will emit the pad-added - signal, to let the client know about the newly found decoded stream. - For unknown streams (which might be the whole stream), it will emit - the unknown-type signal. The application is then - responsible for reporting the error to the user. - - - -]]> - -[.. my_bus_callback goes here ..] - - -\n", argv[0]); - return -1; - } - - /* setup */ - pipeline = gst_pipeline_new ("pipeline"); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, my_bus_callback, loop); - gst_object_unref (bus); - - src = gst_element_factory_make ("filesrc", "source"); - g_object_set (G_OBJECT (src), "location", argv[1], NULL); - dec = gst_element_factory_make ("decodebin", "decoder"); - g_signal_connect (dec, "pad-added", G_CALLBACK (cb_newpad), NULL); - gst_bin_add_many (GST_BIN (pipeline), src, dec, NULL); - gst_element_link (src, dec); - - /* create audio output */ - audio = gst_bin_new ("audiobin"); - conv = gst_element_factory_make ("audioconvert", "aconv"); - audiopad = gst_element_get_static_pad (conv, "sink"); - sink = gst_element_factory_make ("alsasink", "sink"); - gst_bin_add_many (GST_BIN (audio), conv, sink, NULL); - gst_element_link (conv, sink); - gst_element_add_pad (audio, - gst_ghost_pad_new ("sink", audiopad)); - gst_object_unref (audiopad); - gst_bin_add (GST_BIN (pipeline), audio); - - /* run */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - g_main_loop_run (loop); - - /* cleanup */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - - return 0; -} -]]> - - - Decodebin, similar to playbin, supports the following features: - - - - - Can decode an unlimited number of contained streams to decoded - output pads. - - - - - Is handled as a GstElement in all ways, - including tag or error forwarding and state handling. - - - - - Although decodebin is a good autoplugger, there's a whole lot of - things that it does not do and is not intended to do: - - - - - Taking care of input streams with a known media type (e.g. a DVD, - an audio-CD or such). - - - - - Selection of streams (e.g. which audio track to play in case of - multi-language media streams). - - - - - Overlaying subtitles over a decoded video stream. - - - - - Decodebin can be easily tested on the commandline, e.g. by using the - command gst-launch-1.0 filesrc location=file.ogg ! decodebin - ! audioconvert ! audioresample ! autoaudiosink. - - - - - URIDecodebin - - The uridecodebin element is very similar to decodebin, only that it - automatically plugs a source plugin based on the protocol of the URI - given. - - - Uridecodebin will also automatically insert buffering elements when - the uri is a slow network source. The buffering element will post - BUFFERING messages that the application needs to handle as explained - in . - The following properties can be used to configure the buffering method: - - - - - The buffer-size property allows you to configure a maximum size in - bytes for the buffer element. - - - - - The buffer-duration property allows you to configure a maximum size - in time for the buffer element. The time will be estimated based on - the bitrate of the network. - - - - - With the download property you can enable the download buffering - method as described in . - Setting this option to TRUE will only enable download buffering - for selected formats such as quicktime, flash video, avi and - webm. - - - - - You can also enable buffering on the parsed/demuxed data with the - use-buffering property. This is interesting to enable buffering - on slower random access media such as a network file server. - - - - - URIDecodebin can be easily tested on the commandline, e.g. by using the - command gst-launch-1.0 uridecodebin uri=file:///file.ogg ! - ! audioconvert ! audioresample ! autoaudiosink. - - - - - Playsink - - The playsink element is a powerful sink element. It has request pads - for raw decoded audio, video and text and it will configure itself to - play the media streams. It has the following features: - - - - - It exposes GstStreamVolume, GstVideoOverlay, GstNavigation and - GstColorBalance interfaces and automatically plugs software - elements to implement the interfaces when needed. - - - - - It will automatically plug conversion elements. - - - - - Can optionally render visualizations when there is no video input. - - - - - Configurable sink elements. - - - - - Configurable audio/video sync offset to fine-tune synchronization - in badly muxed files. - - - - - Support for taking a snapshot of the last video frame. - - - - - Below is an example of how you can use playsink. We use a uridecodebin - element to decode into raw audio and video streams which we then link - to the playsink request pads. We only link the first audio and video - pads, you could use an input-selector to link all pads. - - - - -]]> - -[.. my_bus_callback goes here ..] - - - - -\n", argv[0]); - return -1; - } - - /* setup */ - pipeline = gst_pipeline_new ("pipeline"); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, my_bus_callback, loop); - gst_object_unref (bus); - - dec = gst_element_factory_make ("uridecodebin", "source"); - g_object_set (G_OBJECT (dec), "uri", argv[1], NULL); - g_signal_connect (dec, "pad-added", G_CALLBACK (cb_pad_added), NULL); - - /* create audio output */ - sink = gst_element_factory_make ("playsink", "sink"); - gst_util_set_object_arg (G_OBJECT (sink), "flags", - "soft-colorbalance+soft-volume+vis+text+audio+video"); - gst_bin_add_many (GST_BIN (pipeline), dec, sink, NULL); - - /* run */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - g_main_loop_run (loop); - - /* cleanup */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - - return 0; -} -]]> - - - - This example will show audio and video depending on what you - give it. Try this example on an audio file and you will see that - it shows visualizations. You can change the visualization at runtime by - changing the vis-plugin property. - - - diff --git a/docs/manual/highlevel-xml.xml b/docs/manual/highlevel-xml.xml deleted file mode 100644 index e330616636..0000000000 --- a/docs/manual/highlevel-xml.xml +++ /dev/null @@ -1,17 +0,0 @@ - - XML in <application>GStreamer</application> (deprecated) - - GStreamer used to provide functions to - save pipeline definitions into XML format and later restore them - again from XML. - - - - This never really worked properly for all but the most simple use cases - though, and is also pretty much impossible to make work correctly in a - useful way due to the dynamic nature of almost all non-trivial GStreamer - pipelines. Consequently, this API has been deprecated and will be - removed at some point. Don't use it. - - - diff --git a/docs/manual/images/.gitignore b/docs/manual/images/.gitignore deleted file mode 100644 index 68a2009bf3..0000000000 --- a/docs/manual/images/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.eps -*.png diff --git a/docs/manual/intro-basics.xml b/docs/manual/intro-basics.xml deleted file mode 100644 index 0c385b1a1c..0000000000 --- a/docs/manual/intro-basics.xml +++ /dev/null @@ -1,159 +0,0 @@ - - Foundations - - This chapter of the guide introduces the basic concepts of &GStreamer;. - Understanding these concepts will be important in reading any of the - rest of this guide, all of them assume understanding of these basic - concepts. - - - - Elements - - An element is the most important class of objects - in &GStreamer;. You will usually create a chain of elements linked - together and let data flow through this chain of elements. An element - has one specific function, which can be the reading of data from a - file, decoding of this data or outputting this data to your sound - card (or anything else). By chaining together several such elements, - you create a pipeline that can do a specific task, - for example media playback or capture. &GStreamer; ships with a large - collection of elements by default, making the development of a large - variety of media applications possible. If needed, you can also write - new elements. That topic is explained in great deal in the &GstPWG;. - - - - - Pads - - Pads are element's input and output, where - you can connect other elements. They are used to negotiate links and - data flow - between elements in &GStreamer;. A pad can be viewed as a - plug or port on an element where - links may be made with other elements, and through which data can - flow to or from those elements. Pads have specific data handling - capabilities: a pad can restrict the type of data that flows - through it. Links are only allowed between two pads when the - allowed data types of the two pads are compatible. Data types are - negotiated between pads using a process called caps - negotiation. Data types are described as a - GstCaps. - - - An analogy may be helpful here. A pad is similar to a plug or jack on a - physical device. Consider, for example, a home theater system consisting - of an amplifier, a DVD player, and a (silent) video projector. Linking - the DVD player to the amplifier is allowed because both devices have audio - jacks, and linking the projector to the DVD player is allowed because - both devices have compatible video jacks. Links between the - projector and the amplifier may not be made because the projector and - amplifier have different types of jacks. Pads in &GStreamer; serve the - same purpose as the jacks in the home theater system. - - - For the most part, all data in &GStreamer; flows one way through a link - between elements. Data flows out of one element through one or more - source pads, and elements accept incoming data - through one or more sink pads. Source and sink - elements have only source and sink pads, respectively. Data usually - means buffers (described by the - GstBuffer object) and events (described - by the - GstEvent object). - - - - - Bins and pipelines - - - A bin is a container for a collection of elements. - Since bins are subclasses of elements - themselves, you can mostly control a bin as if it were an element, - thereby abstracting away a lot of complexity for your application. You - can, for example change state on all elements in a bin by changing the - state of that bin itself. Bins also forward bus messages from their - contained children (such as error messages, tag messages or EOS messages). - - - A pipeline is a top-level bin. It provides a bus for - the application and manages the synchronization for its children. - As you set it to PAUSED or PLAYING state, data flow will start and media - processing will take place. Once started, pipelines will run in a - separate thread until you stop them or the end - of the data stream is reached. - - -

- &GStreamer; pipeline for a simple ogg player - - - - - -
- - - - - Communication - - - &GStreamer; provides several mechanisms for communication and data exchange - between the application and the pipeline. - - - - - - buffers are objects for passing streaming data - between elements in the pipeline. Buffers always travel from sources - to sinks (downstream). - - - - - events are objects sent between elements or from - the application to elements. Events can travel upstream and downstream. - Downstream events can be synchronised to the data flow. - - - - - messages are objects posted by elements on - the pipeline's message bus, where they will be held for collection - by the application. Messages can be intercepted synchronously from - the streaming thread context of the element posting the message, but - are usually handled asynchronously by the application from the - application's main thread. Messages are used to transmit information - such as errors, tags, state changes, buffering state, redirects etc. - from elements to the application in a thread-safe way. - - - - - queries allow applications to request information - such as duration or current playback position from the pipeline. - Queries are always answered synchronously. Elements can also use - queries to request information from their peer elements (such as the - file size or duration). They can be used both ways within a pipeline, - but upstream queries are more common. - - - - -
- &GStreamer; pipeline with different communication flows - - - - - -
- -
- - diff --git a/docs/manual/intro-gstreamer.xml b/docs/manual/intro-gstreamer.xml deleted file mode 100644 index 38329e8cd6..0000000000 --- a/docs/manual/intro-gstreamer.xml +++ /dev/null @@ -1,99 +0,0 @@ - - What is &GStreamer;? - - - - - - &GStreamer; is a framework for creating streaming media applications. - The fundamental design comes from the video pipeline at Oregon Graduate - Institute, as well as some ideas from DirectShow. - - - - &GStreamer;'s development framework makes it possible to write any - type of streaming multimedia application. The &GStreamer; framework - is designed to make it easy to write applications that handle audio - or video or both. It isn't restricted to audio and video, and can - process any kind of data flow. - The pipeline design is made to have little overhead above what the - applied filters induce. This makes &GStreamer; a good framework for - designing even high-end audio applications which put high demands on - latency. - - - - One of the most obvious uses of &GStreamer; is using it to build - a media player. &GStreamer; already includes components for building a - media player that can support a very wide variety of formats, including - MP3, Ogg/Vorbis, MPEG-1/2, AVI, Quicktime, mod, and more. &GStreamer;, - however, is much more than just another media player. Its main advantages - are that the pluggable components can be mixed and matched into arbitrary - pipelines so that it's possible to write a full-fledged video or audio - editing application. - - - - The framework is based on plugins that will provide the various codec - and other functionality. The plugins can be linked and arranged in - a pipeline. This pipeline defines the flow of the data. Pipelines can - also be edited with a GUI editor and saved as XML so that pipeline - libraries can be made with a minimum of effort. - - - - The &GStreamer; core function is to provide a framework for plugins, - data flow and media type handling/negotiation. It also provides an - API to write applications using the various plugins. - - - - - Specifically, &GStreamer; provides - - an API for multimedia applications - a plugin architecture - a pipeline architecture - a mechanism for media type handling/negotiation - a mechanism for synchronization - over 250 plug-ins providing more than 1000 elements - a set of tools - - - - - &GStreamer; plug-ins could be classified into - - protocols handling - sources: for audio and video (involves protocol plugins) - formats: parsers, formaters, muxers, demuxers, metadata, subtitles - codecs: coders and decoders - filters: converters, mixers, effects, ... - sinks: for audio and video (involves protocol plugins) - - - -
- Gstreamer overview - - - - - -
- - - &GStreamer; is packaged into - - gstreamer: the core package - gst-plugins-base: an essential exemplary set of elements - gst-plugins-good: a set of good-quality plug-ins under LGPL - gst-plugins-ugly: a set of good-quality plug-ins that might pose distribution problems - gst-plugins-bad: a set of plug-ins that need more quality - gst-libav: a set of plug-ins that wrap libav for decoding and encoding - a few others packages - - - - -
diff --git a/docs/manual/intro-motivation.xml b/docs/manual/intro-motivation.xml deleted file mode 100644 index 55571b6a14..0000000000 --- a/docs/manual/intro-motivation.xml +++ /dev/null @@ -1,300 +0,0 @@ - - Design principles - - - -
- Clean and powerful - - &GStreamer; provides a clean interface to: - - - - - The application programmer who wants to build a media pipeline. - The programmer can use an extensive set of powerful tools to create - media pipelines without writing a single line of code. Performing - complex media manipulations becomes very easy. - - - - - The plugin programmer. Plugin programmers are provided a clean and - simple API to create self-contained plugins. An extensive debugging - and tracing mechanism has been integrated. GStreamer also comes with - an extensive set of real-life plugins that serve as examples too. - - - - -
-
- Object oriented - - &GStreamer; adheres to GObject, the GLib 2.0 object model. A programmer - familiar with GLib 2.0 or GTK+ will be - comfortable with &GStreamer;. - - - &GStreamer; uses the mechanism of signals and object properties. - - - All objects can be queried at runtime for their various properties and - capabilities. - - - &GStreamer; intends to be similar in programming methodology to GTK+. - This applies to the object model, ownership of objects, reference - counting, etc. - -
- -
- Extensible - - All &GStreamer; Objects can be extended using the GObject - inheritance methods. - - - All plugins are loaded dynamically and can be extended and upgraded - independently. - -
- -
- Allow binary-only plugins - - Plugins are shared libraries that are loaded at runtime. Since all - the properties of the plugin can be set using the GObject properties, - there is no need (and in fact no way) to have any header files - installed for the plugins. - - - Special care has been taken to make plugins completely self-contained. - All relevant aspects of plugins can be queried at run-time. - -
- -
- High performance - - High performance is obtained by: - - - - - using GLib's GSlice allocator - - - - - extremely light-weight links between plugins. Data can travel - the pipeline with minimal overhead. Data passing between - plugins only involves a pointer dereference in a typical - pipeline. - - - - - providing a mechanism to directly work on the target memory. - A plugin can for example directly write to the X server's - shared memory space. Buffers can also point to arbitrary - memory, such as a sound card's internal hardware buffer. - - - - - refcounting and copy on write minimize usage of memcpy. - Sub-buffers efficiently split buffers into manageable pieces. - - - - - dedicated streaming threads, with scheduling handled by the kernel. - - - - - allowing hardware acceleration by using specialized plugins. - - - - - using a plugin registry with the specifications of the plugins so - that the plugin loading can be delayed until the plugin is actually - used. - - - -
- -
- Clean core/plugins separation - - The core of &GStreamer; is essentially media-agnostic. It only knows - about bytes and blocks, and only contains basic elements. - The core of &GStreamer; is functional enough to even implement - low-level system tools, like cp. - - - All of the media handling functionality is provided by plugins - external to the core. These tell the core how to handle specific - types of media. - -
- -
- Provide a framework for codec experimentation - - &GStreamer; also wants to be an easy framework where codec - developers can experiment with different algorithms, speeding up the - development of open and free multimedia codecs like those developed - by the Xiph.Org - Foundation (such as Theora and Vorbis). - -
- - -
diff --git a/docs/manual/intro-preface.xml b/docs/manual/intro-preface.xml deleted file mode 100644 index f32339ea4e..0000000000 --- a/docs/manual/intro-preface.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - Who should read this manual? - - This book is about &GStreamer; from an application developer's point of view; it - describes how to write a &GStreamer; application using the &GStreamer; - libraries and tools. For an explanation about writing plugins, we - suggest the Plugin - Writers Guide. - - - Also check out the other documentation available on the &GStreamer; web site. - - - - - - - Preliminary reading - - In order to understand this manual, you need to have a basic - understanding of the C language. - - - Since &GStreamer; adheres to the GObject programming model, this guide - also assumes that you understand the basics of GObject and glib programming. - - Especially, - - GObject instantiation - GObject properties (set/get) - GObject casting - GObject referecing/dereferencing - glib memory management - glib signals and callbacks - glib main loop - - - - - - - - Structure of this manual - - To help you navigate through this guide, it is divided into several large - parts. Each part addresses a particular broad topic concerning &GStreamer; - appliction development. The parts of this guide are laid out in the following - order: - - - - gives you an overview of &GStreamer;, - it's design principles and foundations. - - - - covers the basics of &GStreamer; - application programming. At the end of this part, you should be - able to build your own audio player using &GStreamer; - - - - In , we will move on to advanced - subjects which make &GStreamer; stand out of its competitors. We - will discuss application-pipeline interaction using dynamic parameters - and interfaces, we will discuss threading and threaded pipelines, - scheduling and clocks (and synchronization). Most of those topics are - not just there to introduce you to their API, but primarily to give - a deeper insight in solving application programming problems with - &GStreamer; and understanding their concepts. - - - - Next, in , we will go into higher-level - programming APIs for &GStreamer;. You don't exactly need to know all - the details from the previous parts to understand this, but you will - need to understand basic &GStreamer; concepts nevertheless. We will, - amongst others, discuss XML, playbin and autopluggers. - - - - Finally in , you will find some random - information on integrating with GNOME, KDE, OS X or Windows, some - debugging help and general tips to improve and simplify &GStreamer; - programming. - - diff --git a/docs/manual/linked-elements.png b/docs/manual/linked-elements.png deleted file mode 100644 index de75adf215b576f65eef8788f165d17ff770467d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7708 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 Pxfm)6VEJ-cv(Wzm7fkmA diff --git a/docs/manual/manual.xml b/docs/manual/manual.xml deleted file mode 100644 index ac268b5485..0000000000 --- a/docs/manual/manual.xml +++ /dev/null @@ -1,269 +0,0 @@ - - -%image-entities; - -%version-entities; - -%url-entities; - - - - The code for this example is automatically extracted from - the documentation and built under tests/examples/manual - in the GStreamer tarball. - - -"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -GStreamer"> -GStreamer Plugin Writer's Guide"> -]> - - - &TITLEPAGE; - - - -Foreword - - &GStreamer; is an extremely powerful and versatile framework for - creating streaming media applications. Many of the virtues of the - &GStreamer; framework come from its modularity: &GStreamer; can - seamlessly incorporate new plugin modules. But because modularity - and power often come at a cost of greater complexity, writing new - applications is not always easy. - - - This guide is intended to help you understand the &GStreamer; - framework (version &GST_VERSION;) so you can develop applications - based on it. The first chapters will focus on development of a - simple audio player, with much effort going into helping you - understand &GStreamer; concepts. Later chapters will go into - more advanced topics related to media playback, but also at - other forms of media processing (capture, editing, etc.). - - - - -Introduction - - &INTRO; - - - - - - - About GStreamer - - - This part gives you an overview of the technologies described in - this book. - - - - &GSTREAMER; - &MOTIVATION; - &CONCEPTS; - - - - - - - Building an Application - - - In these chapters, we will discuss the basic concepts of &GStreamer; - and the most-used objects, such as elements, pads and buffers. We - will use a visual representation of these objects so that we can - visualize the more complex pipelines you will learn to build later - on. You will get a first glance at the &GStreamer; API, which should - be enough for building elementary applications. Later on in this - part, you will also learn to build a basic command-line application. - - - Note that this part will give a look into the low-level API and - concepts of &GStreamer;. Once you're going to build applications, - you might want to use higher-level APIs. Those will be discussed - later on in this manual. - - - - &INIT; - &ELEMENTS; - &BINS; - &BUS; - &PADS; - &DATA; - &HELLOWORLD; - - - - - - - Advanced &GStreamer; concepts - - - In this part we will cover the more advanced features of &GStreamer;. - With the basics you learned in the previous part you should be - able to create a simple application. However, - &GStreamer; provides much more candy than just the basics of playing - back audio files. In this chapter, you will learn more of the - low-level features and internals of &GStreamer;. - - - Some parts of this part will serve mostly as an explanation of - how &GStreamer; works internally; they are not actually needed for - actual application development. This includes chapters such as the - ones covering scheduling, autoplugging and synchronization. Other - chapters, however, discuss more advanced ways of - pipeline-application interaction, and can turn out to be very useful - for certain applications. This includes the chapters on metadata, - querying and events, interfaces, dynamic parameters and pipeline - data manipulation. - - - - &QUERYEVENTS; - &METADATA; - &INTERFACES; - &CLOCKS; - &BUFFERING; - &DPARAMS; - &THREADS; - &AUTOPLUGGING; - &DATAACCESS; - - - - - - - Higher-level interfaces for &GStreamer; applications - - - In the previous two parts, you have learned many of the internals - and their corresponding low-level interfaces into &GStreamer; - application programming. Many people will, however, not need so - much control (and as much code), but will prefer to use a standard - playback interface that does most of the difficult internals for - them. In this chapter, we will introduce you into the concept of - autopluggers, playback managing elements and other such things. - Those higher-level interfaces are intended to - simplify &GStreamer;-based application programming. They do, however, - also reduce the flexibility. It is up to the application developer - to choose which interface he will want to use. - - - - &PLAYBACK; - - - - - - - Appendices - - - By now, you've learned all about the internals of &GStreamer; and - application programming using the &GStreamer; framework. This part - will go into some random bits that are useful to know if you're - going to use &GStreamer; for serious application programming. It - will touch upon things related to integration with popular desktop - environments that we run on (GNOME, KDE, OS X, Windows), it will - shortly explain how applications included with &GStreamer; can help - making your life easier, and some information on debugging. - - - In addition, we also provide a porting guide which will explain - easily how to port &GStreamer;-0.10 applications to &GStreamer;-1.0. - - - - - - &PROGRAMS; - &COMPILING; - &CHECKLIST; - &PORTING; - &INTEGRATION; - &LICENSING; - "ES; - - - diff --git a/docs/manual/mime-world.png b/docs/manual/mime-world.png deleted file mode 100644 index f1e51f2cccafeacd20cc3ac18fc2733e41296809..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48705 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 diff --git a/docs/manual/outline.txt b/docs/manual/outline.txt deleted file mode 100644 index c05b512f9f..0000000000 --- a/docs/manual/outline.txt +++ /dev/null @@ -1,92 +0,0 @@ -Overview - Introduction - (creating multimedia apps) - (pipeline/plugin based) - - Motivation - (multitude of duplicate code) - (mostly focused on one goal) - (reinvent plugin mechanisms) - (network transparency?) - (catch up with Windows(tm) world) - - Goals - (clean and powerfull) - (building graphs) - (building plugins) - (object oriented) - (using GTK+ object model) - (extensible) - (alow binary only plugins) - (alow high performance) - (HW acceleration) - (efficient memory use) - (kernel buffers etc..) - -Basic concepts - elements - (what is it) - (types) sink, src, filter - (have pads) - linking elements - bin - (can contain elements) - pipeline (a complete graph) - thread (theaded operation) - buffers - (pass between elements) - (contains data) - (can cary metadata) - (use refcounting) - element states - (null) - (ready) - (paused) - (playing) - -Building apps - helloworld - (fdsrc->mp3decoder->audiosink) - (step by step explanation) - More on factories - problems with helloworld - MIME types - GStreamer types - Basic types - Your second application - - - -advanced concepts - threads - queues - cothreads - dynamic pipeline construction - ghost pads - type detection - utility functions - -XML in GStreamer - (saving) - (loading a pipeline) - -Plugin development - plugin types - chain based - loop based - buffers - metadata - subbuffers - adding pads - libraries - plugin registry - types - type detection - QoS messages - clocks - -GStreamer programs - editor - gstplay - - diff --git a/docs/manual/simple-player.png b/docs/manual/simple-player.png deleted file mode 100644 index b3b3ca1c50e9c5c0700d0fa5f84eab1fa6acc1dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53147 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 diff --git a/docs/manual/sink-element.png b/docs/manual/sink-element.png deleted file mode 100644 index 6a4eaa1a379d1ecf88e8551e29ab96c0ed18f6fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3369 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 diff --git a/docs/manual/src-element.png b/docs/manual/src-element.png deleted file mode 100644 index 27699e05b4c2d3432d0e879d1318cbc11107519c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3611 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 diff --git a/docs/manual/state-diagram.svg b/docs/manual/state-diagram.svg deleted file mode 100644 index 1be6d42a15..0000000000 --- a/docs/manual/state-diagram.svg +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NULL - - READY - - PLAYING - - PAUSED - - - diff --git a/docs/manual/thread-buffering.png b/docs/manual/thread-buffering.png deleted file mode 100644 index 006c602f8194daeadcc0f95af6dd7d0e4475ccdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23327 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 diff --git a/docs/manual/thread-synchronizing.png b/docs/manual/thread-synchronizing.png deleted file mode 100644 index 99c0a7bf3dc0cad72ed6d0ca9f4cf8dade0b20fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43061 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 F{{biZ$MXOH diff --git a/docs/manual/titlepage.xml b/docs/manual/titlepage.xml deleted file mode 100644 index 3883384a4e..0000000000 --- a/docs/manual/titlepage.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - Wim - Taymans - - - wim.taymans@chello.be - - - - - - Steve - Baker - - - stevebaker_org@yahoo.co.uk - - - - - - Andy - Wingo - - - wingo@pobox.com - - - - - - Ronald - S. - Bultje - - - rbultje@ronald.bitfreak.net - - - - - - Stefan - Kost - - - ensonic@users.sf.net - - - - - - - - This material may be distributed only subject to the terms and - conditions set forth in the Open Publication License, v1.0 or later (the - latest version is presently available at http://www.opencontent.org/opl.shtml). - - - - &GStreamer; Application Development Manual (&GST_VERSION;) - - - diff --git a/docs/pwg/.gitignore b/docs/pwg/.gitignore deleted file mode 100644 index db6eb2ffb1..0000000000 --- a/docs/pwg/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -.deps -build -html -*.pdf -*.ps diff --git a/docs/pwg/Makefile.am b/docs/pwg/Makefile.am deleted file mode 100644 index 0228a313b0..0000000000 --- a/docs/pwg/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -### this is the part you can customize if you need to - -# base name of doc -DOC = pwg -# formats defined for upload-doc.mak -FORMATS=html ps pdf - -# main xml file -MAIN = $(DOC).xml -# all xml sources -XML = $(notdir $(wildcard $(srcdir)/*.xml)) -# base style sheet -CSS = base.css - -# image sources -PNG_SRC = -FIG_SRC = $(notdir $(wildcard $(srcdir)/*.fig)) - -# extra sources to copy in build directory -EXTRA_SRC = - -### this is the generic bit and you shouldn't need to change this - -# get the generic docbuilding Makefile stuff -include $(srcdir)/../manuals.mak -# get the generic upload target -include $(top_srcdir)/common/upload-doc.mak - -### this is standard automake stuff - -# package up all the source -EXTRA_DIST = $(SRC) - -# install documentation -pwgdir = $(docdir)/$(DOC) -pwg_DATA = $(PDF_DAT) $(PS_DAT) - -include $(srcdir)/../htmlinstall.mak diff --git a/docs/pwg/advanced-allocation.xml b/docs/pwg/advanced-allocation.xml deleted file mode 100644 index e7346bd36f..0000000000 --- a/docs/pwg/advanced-allocation.xml +++ /dev/null @@ -1,817 +0,0 @@ - - Memory allocation - - Memory allocation and management is a very important topic in - multimedia. High definition video uses many megabytes to store - one single frame of video. It is important to reuse the memory - when possible instead of constantly allocating and freeing - the memory. - - - Multimedia systems usually use special purpose chips, such as - DSPs or GPUs to perform the heavy lifting (especially for video). - These special purpose chips have usually strict requirements - for the memory that they can operate on and how the memory - is accessed. - - - This chapter talks about the memory management features that - &GStreamer; plugins can use. We will first talk about the - lowlevel GstMemory object that manages - access to a piece of memory. We then continue with - GstBuffer that is used to exchange data - between plugins (and the application) and that uses - GstMemory. We talk about - GstMeta that can be placed on buffers to - give extra info about the buffer and its memory. - For efficiently managing buffers of the same size, we take a - look at GstBufferPool. To conclude this - chapter we take a look at the GST_QUERY_ALLOCATION query that - is used to negotiate memory management options between elements. - - - - GstMemory - - GstMemory is an object that manages a region - of memory. The memory object points to a region of memory of - maxsize. The area in this memory starting at - offset and for size bytes is the - accessible region in the memory. the maxsize of the memory can - never be changed after the object is created, however, the offset - and size can be changed. - - - GstAllocator - - GstMemory objects are created by a - GstAllocator object. Most allocators implement the - default gst_allocator_alloc() method but some allocator - might implement a different method, for example when additional parameters - are needed to allocate the specific memory. - - - Different allocators exist for, for example, system memory, shared memory - and memory backed by a DMAbuf file descriptor. To implement support for a - new kind of memory type, you must implement a new allocator object as shown - below. - - - - GstMemory API example - - Data access to the memory wrapped by the GstMemory - object is always protected with a gst_memory_map() - and gst_memory_unmap() pair. An access mode - (read/write) must be given when mapping memory. The map - function returns a pointer to the valid memory region that can - then be accessed according to the requested access mode. - - - Below is an example of making a GstMemory - object and using the gst_memory_map() to - access the memory region. - - - - - - - - Implementing a GstAllocator - - WRITEME - - - - - - - GstBuffer - - A GstBuffer is an lightweight object that - is passed from an upstream to a downstream element and contains - memory and metadata. It represents the multimedia content that - is pushed or pull downstream by elements. - - - The buffer contains one or more GstMemory - objects that represent the data in the buffer. - - - Metadata in the buffer consists of: - - - - - DTS and PTS timestamps. These represent the decoding and - presentation timestamps of the buffer content and is used by - synchronizing elements to schedule buffers. Both these timestamps - can be GST_CLOCK_TIME_NONE when unknown/undefined. - - - - - The duration of the buffer contents. This duration can be - GST_CLOCK_TIME_NONE when unknown/undefined. - - - - - Media specific offsets and offset_end. For video this is the - frame number in the stream and for audio the sample number. Other - definitions for other media exist. - - - - - Arbitrary structures via GstMeta, see below. - - - - - - GstBuffer writability - - A buffer is writable when the refcount of the object is exactly 1, meaning - that only one object is holding a ref to the buffer. You can only - modify anything in the buffer when the buffer is writable. This means - that you need to call gst_buffer_make_writable() - before changing the timestamps, offsets, metadata or adding and - removing memory blocks. - - - - GstBuffer API examples - - You can create a buffer with gst_buffer_new () - and then add memory objects to it or you can use a convenience function - gst_buffer_new_allocate () which combines the - two. It's also possible to wrap existing memory with - gst_buffer_new_wrapped_full () where you can - give the function to call when the memory should be freed. - - - You can access the memory of the buffer by getting and mapping the - GstMemory objects individually or by using - gst_buffer_map (). The latter merges all the - memory into one big block and then gives you a pointer to this block. - - - Below is an example of how to create a buffer and access its memory. - - - - - - - - - GstMeta - - With the GstMeta system you can add arbitrary - structures on buffers. These structures describe extra properties - of the buffer such as cropping, stride, region of interest etc. - - - The metadata system separates API specification (what the metadata - and its API look like) and the implementation (how it works). This makes - it possible to make different implementations of the same API, - for example, depending on the hardware you are running on. - - - - GstMeta API example - - After allocating a new buffer, you can add metadata to the buffer - with the metadata specific API. This means that you will need to - link to the header file where the metadata is defined to use - its API. - - - By convention, a metadata API with name FooBar - should provide two methods, a - gst_buffer_add_foo_bar_meta () and a - gst_buffer_get_foo_bar_meta (). Both functions - should return a pointer to a FooBarMeta - structure that contains the metadata fields. Some of the - _add_*_meta () can have extra parameters that - will usually be used to configure the metadata structure for you. - - - Let's have a look at the metadata that is used to specify a cropping - region for video frames. - - - - -[...] - GstVideoCropMeta *meta; - - /* buffer points to a video frame, add some cropping metadata */ - meta = gst_buffer_add_video_crop_meta (buffer); - - /* configure the cropping metadata */ - meta->x = 8; - meta->y = 8; - meta->width = 120; - meta->height = 80; -[...] -]]> - - - An element can then use the metadata on the buffer when rendering - the frame like this: - - - - -[...] - GstVideoCropMeta *meta; - - /* buffer points to a video frame, get the cropping metadata */ - meta = gst_buffer_get_video_crop_meta (buffer); - - if (meta) { - /* render frame with cropping */ - _render_frame_cropped (buffer, meta->x, meta->y, meta->width, meta->height); - } else { - /* render frame */ - _render_frame (buffer); - } -[...] - -]]> - - - - - Implementing new GstMeta - - In the next sections we show how you can add new metadata to the - system and use it on buffers. - - - - Define the metadata API - - First we need to define what our API will look like and we - will have to register this API to the system. This is important - because this API definition will be used when elements negotiate - what kind of metadata they will exchange. The API definition - also contains arbitrary tags that give hints about what the - metadata contains. This is important when we see how metadata - is preserved when buffers pass through the pipeline. - - - If you are making a new implementation of an existing API, - you can skip this step and move on to the implementation step. - - - First we start with making the - my-example-meta.h header file that will contain - the definition of the API and structure for our metadata. - - - - -typedef struct _MyExampleMeta MyExampleMeta; - -struct _MyExampleMeta { - GstMeta meta; - - gint age; - gchar *name; -}; - -GType my_example_meta_api_get_type (void); -#define MY_EXAMPLE_META_API_TYPE (my_example_meta_api_get_type()) - -#define gst_buffer_get_my_example_meta(b) \ - ((MyExampleMeta*)gst_buffer_get_meta((b),MY_EXAMPLE_META_API_TYPE)) -]]> - - - The metadata API definition consists of the definition of the - structure that holds a gint and a string. The first field in - the structure must be GstMeta. - - - We also define a my_example_meta_api_get_type () - function that will register out metadata API definition. We - also define a convenience macro - gst_buffer_get_my_example_meta () that simply - finds and returns the metadata with our new API. - - - Next let's have a look at how the - my_example_meta_api_get_type () function is - implemented in the my-example-meta.c file. - - - - - - As you can see, it simply uses the - gst_meta_api_type_register () function to - register a name for the api and some tags. The result is a - new pointer GType that defines the newly registered API. - - - - - Implementing a metadata API - - Next we can make an implementation for a registered metadata - API GType. The implementation detail of a metadata API - are kept in a GstMetaInfo structure - that you will make available to the users of your metadata - API implementation with a my_example_meta_get_info () - function and a convenience MY_EXAMPLE_META_INFO - macro. You will also make a method to add your metadata - implementation to a GstBuffer. - Your my-example-meta.h header file will - need these additions: - - - - - - Let's have a look at how these functions are - implemented in the my-example-meta.c file. - - -age = 0; - emeta->name = NULL; - - return TRUE; -} - -static gboolean -my_example_meta_transform (GstBuffer * transbuf, GstMeta * meta, - GstBuffer * buffer, GQuark type, gpointer data) -{ - MyExampleMeta *emeta = (MyExampleMeta *) meta; - - /* we always copy no matter what transform */ - gst_buffer_add_my_example_meta (transbuf, emeta->age, emeta->name); - - return TRUE; -} - -static void -my_example_meta_free (GstMeta * meta, GstBuffer * buffer) -{ - MyExampleMeta *emeta = (MyExampleMeta *) meta; - - g_free (emeta->name); - emeta->name = NULL; -} - -const GstMetaInfo * -my_example_meta_get_info (void) -{ - static const GstMetaInfo *meta_info = NULL; - - if (g_once_init_enter (&meta_info)) { - const GstMetaInfo *mi = gst_meta_register (MY_EXAMPLE_META_API_TYPE, - "MyExampleMeta", - sizeof (MyExampleMeta), - my_example_meta_init, - my_example_meta_free, - my_example_meta_transform); - g_once_init_leave (&meta_info, mi); - } - return meta_info; -} - -MyExampleMeta * -gst_buffer_add_my_example_meta (GstBuffer *buffer, - gint age, - const gchar *name) -{ - MyExampleMeta *meta; - - g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); - - meta = (MyExampleMeta *) gst_buffer_add_meta (buffer, - MY_EXAMPLE_META_INFO, NULL); - - meta->age = age; - meta->name = g_strdup (name); - - return meta; -} -]]> - - - gst_meta_register () registers the implementation - details, like the API that you implement and the size of the - metadata structure along with methods to initialize and free the - memory area. You can also implement a transform function that will - be called when a certain transformation (identified by the quark and - quark specific data) is performed on a buffer. - - - Lastly, you implement a gst_buffer_add_*_meta() - that adds the metadata implementation to a buffer and sets the - values of the metadata. - - - - - - - - GstBufferPool - - The GstBufferPool object provides a convenient - base class for managing lists of reusable buffers. Essential for this - object is that all the buffers have the same properties such as size, - padding, metadata and alignment. - - - A bufferpool object can be configured to manage a minimum and maximum - amount of buffers of a specific size. A bufferpool can also be - configured to use a specific GstAllocator for - the memory of the buffers. There is support in the bufferpool to enable - bufferpool specific options, such as adding GstMeta - to the buffers in the pool or such as enabling specific padding on - the memory in the buffers. - - - A Bufferpool can be inactivate and active. In the inactive state, - you can configure the pool. In the active state, you can't change - the configuration anymore but you can acquire and release buffers - from/to the pool. - - - In the following sections we take a look at how you can use - a bufferpool. - - - - GstBufferPool API example - - Many different bufferpool implementations can exist; they are all - subclasses of the base class GstBufferPool. - For this example, we will assume we somehow have access to a - bufferpool, either because we created it ourselves or because - we were given one as a result of the ALLOCATION query as we will - see below. - - - The bufferpool is initially in the inactive state so that we can - configure it. Trying to configure a bufferpool that is not in the - inactive state will fail. Likewise, trying to activate a bufferpool - that is not configured will fail. - - - - - - The configuration of the bufferpool is maintained in a generic - GstStructure that can be obtained with - gst_buffer_pool_get_config(). Convenience - methods exist to get and set the configuration options in this - structure. After updating the structure, it is set as the current - configuration in the bufferpool again with - gst_buffer_pool_set_config(). - - - The following options can be configured on a bufferpool: - - - - - The caps of the buffers to allocate. - - - - - The size of the buffers. This is the suggested size of the - buffers in the pool. The pool might decide to allocate larger - buffers to add padding. - - - - - The minimum and maximum amount of buffers in the pool. When - minimum is set to > 0, the bufferpool will pre-allocate this - amount of buffers. When maximum is not 0, the bufferpool - will allocate up to maximum amount of buffers. - - - - - The allocator and parameters to use. Some bufferpools might - ignore the allocator and use its internal one. - - - - - Other arbitrary bufferpool options identified with a string. - a bufferpool lists the supported options with - gst_buffer_pool_get_options() and you - can ask if an option is supported with - gst_buffer_pool_has_option(). The option - can be enabled by adding it to the configuration structure - with gst_buffer_pool_config_add_option (). - These options are used to enable things like letting the - pool set metadata on the buffers or to add extra configuration - options for padding, for example. - - - - - After the configuration is set on the bufferpool, the pool can - be activated with - gst_buffer_pool_set_active (pool, TRUE). From - that point on you can use - gst_buffer_pool_acquire_buffer () to retrieve - a buffer from the pool, like this: - - - - - - It is important to check the return value of the acquire function - because it is possible that it fails: When your - element shuts down, it will deactivate the bufferpool and then - all calls to acquire will return GST_FLOW_FLUSHNG. - - - All buffers that are acquired from the pool will have their pool - member set to the original pool. When the last ref is decremented - on the buffer, &GStreamer; will automatically call - gst_buffer_pool_release_buffer() to release - the buffer back to the pool. You (or any other downstream element) - don't need to know if a buffer came from a pool, you can just - unref it. - - - - - Implementing a new GstBufferPool - - WRITEME - - - - - - - GST_QUERY_ALLOCATION - - The ALLOCATION query is used to negotiate - GstMeta, GstBufferPool - and GstAllocator between elements. Negotiation - of the allocation strategy is always initiated and decided by a srcpad - after it has negotiated a format and before it decides to push buffers. - A sinkpad can suggest an allocation strategy but it is ultimately the - source pad that will decide based on the suggestions of the downstream - sink pad. - - - The source pad will do a GST_QUERY_ALLOCATION with the negotiated caps - as a parameter. This is needed so that the downstream element knows - what media type is being handled. A downstream sink pad can answer the - allocation query with the following results: - - - - - An array of possible GstBufferPool suggestions - with suggested size, minimum and maximum amount of buffers. - - - - - An array of GstAllocator objects along with suggested allocation - parameters such as flags, prefix, alignment and padding. These - allocators can also be configured in a bufferpool when this is - supported by the bufferpool. - - - - - An array of supported GstMeta implementations - along with metadata specific parameters. - It is important that the upstream element knows what kind of - metadata is supported downstream before it places that metadata - on buffers. - - - - - When the GST_QUERY_ALLOCATION returns, the source pad will select - from the available bufferpools, allocators and metadata how it will - allocate buffers. - - - - ALLOCATION query example - - Below is an example of the ALLOCATION query. - - - -#include -#include - - GstCaps *caps; - GstQuery *query; - GstStructure *structure; - GstBufferPool *pool; - GstStructure *config; - guint size, min, max; - -[...] - - /* find a pool for the negotiated caps now */ - query = gst_query_new_allocation (caps, TRUE); - - if (!gst_pad_peer_query (scope->srcpad, query)) { - /* query failed, not a problem, we use the query defaults */ - } - - if (gst_query_get_n_allocation_pools (query) > 0) { - /* we got configuration from our peer, parse them */ - gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); - } else { - pool = NULL; - size = 0; - min = max = 0; - } - - if (pool == NULL) { - /* we did not get a pool, make one ourselves then */ - pool = gst_video_buffer_pool_new (); - } - - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); - gst_buffer_pool_config_set_params (config, caps, size, min, max); - gst_buffer_pool_set_config (pool, config); - - /* and activate */ - gst_buffer_pool_set_active (pool, TRUE); - -[...] -]]> - - - This particular implementation will make a custom - GstVideoBufferPool object that is specialized - in allocating video buffers. You can also enable the pool to - put GstVideoMeta metadata on the buffers from - the pool doing - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_META). - - - - - The ALLOCATION query in base classes - - In many baseclasses you will see the following virtual methods for - influencing the allocation strategy: - - - - - propose_allocation () should suggest - allocation parameters for the upstream element. - - - - - decide_allocation () should decide the - allocation parameters from the suggestions received from - downstream. - - - - - Implementors of these methods should modify the given - GstQuery object by updating the pool options - and allocation options. - - - - diff --git a/docs/pwg/advanced-clock.xml b/docs/pwg/advanced-clock.xml deleted file mode 100644 index a0ffc4f836..0000000000 --- a/docs/pwg/advanced-clock.xml +++ /dev/null @@ -1,173 +0,0 @@ - - Clocking - - - When playing complex media, each sound and video sample must be played in a - specific order at a specific time. For this purpose, GStreamer provides a - synchronization mechanism. - - - - Clocks - - Time in &GStreamer; is defined as the value returned from a particular - GstClock object from the method - gst_clock_get_time (). - - - In a typical computer, there are many sources that can be used as a - time source, e.g., the system time, soundcards, CPU performance - counters, ... For this reason, there are many - GstClock implementations available in &GStreamer;. - The clock time doesn't always start from 0 or from some known value. - Some clocks start counting from some known start date, other clocks start - counting since last reboot, etc... - - - As clocks return an absolute measure of time, they are not usually used - directly. Instead, differences between two clock times are used to - measure elapsed time according to a clock. - - - - - Clock running-time - - A clock returns the absolute-time - according to that clock with gst_clock_get_time (). - From the absolute-time is a running-time - calculated, which is simply the difference between a previous snapshot - of the absolute-time called the base-time. - So: - - - running-time = absolute-time - base-time - - - A &GStreamer; GstPipeline object maintains a - GstClock object and a base-time when it goes - to the PLAYING state. The pipeline gives a handle to the selected - GstClock to each element in the pipeline along - with selected base-time. The pipeline will select a base-time in such - a way that the running-time reflects the total time spent in the - PLAYING state. As a result, when the pipeline is PAUSED, the - running-time stands still. - - - Because all objects in the pipeline have the same clock and base-time, - they can thus all calculate the running-time according to the pipeline - clock. - - - - - Buffer running-time - - To calculate a buffer running-time, we need a buffer timestamp and - the SEGMENT event that preceded the buffer. First we can convert - the SEGMENT event into a GstSegment object - and then we can use the - gst_segment_to_running_time () function to - perform the calculation of the buffer running-time. - - - Synchronization is now a matter of making sure that a buffer with a - certain running-time is played when the clock reaches the same - running-time. Usually this task is done by sink elements. Sink also - have to take into account the latency configured in the pipeline and - add this to the buffer running-time before synchronizing to the - pipeline clock. - - - - - - - Obligations of each element. - - - - Let us clarify the contract between GStreamer and each element in the - pipeline. - - - - Non-live source elements - - Non-live source elements must place a timestamp in each buffer that - they deliver when this is possible. They must choose the timestamps - and the values of the SEGMENT event in such a way that the - running-time of the buffer starts from 0. - - - Some sources, such as filesrc, is not able to generate timestamps - on all buffers. It can and must however create a timestamp on the - first buffer (with a running-time of 0). - - - The source then pushes out the SEGMENT event followed by the - timestamped buffers. - - - - - Live source elements - - Live source elements must place a timestamp in each buffer that - they deliver. They must choose the timestamps and the values of the - SEGMENT event in such a way that the running-time of the buffer - matches exactly the running-time of the pipeline clock when the first - byte in the buffer was captured. - - - - - Parser/Decoder/Encoder elements - - Parser/Decoder elements must use the incoming timestamps and transfer - those to the resulting output buffers. They are allowed to interpolate - or reconstruct timestamps on missing input buffers when they can. - - - - - Demuxer elements - - Demuxer elements can usually set the timestamps stored inside the media - file onto the outgoing buffers. They need to make sure that outgoing - buffers that are to be played at the same time have the same - running-time. Demuxers also need to take into account the incoming - timestamps on buffers and use that to calculate an offset on the outgoing - buffer timestamps. - - - - - Muxer elements - - Muxer elements should use the incoming buffer running-time to mux the - different streams together. They should copy the incoming running-time - to the outgoing buffers. - - - - - Sink elements - - If the element is intended to emit samples at a specific time (real time - playing), the element should require a clock, and thus implement the - method set_clock. - - - The sink should then make sure that the sample with running-time is played - exactly when the pipeline clock reaches that running-time + latency. - Some elements might use the clock API such as - gst_clock_id_wait() - to perform this action. Other sinks might need to use other means of - scheduling timely playback of the data. - - - - - diff --git a/docs/pwg/advanced-dparams.xml b/docs/pwg/advanced-dparams.xml deleted file mode 100644 index 4d78c30e8b..0000000000 --- a/docs/pwg/advanced-dparams.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Supporting Dynamic Parameters - - Warning, this part describes 0.10 and is outdated. - - - Sometimes object properties are not powerful enough to control the - parameters that affect the behaviour of your element. - When this is the case you can mark these parameters as being Controllable. - Aware applications can use the controller subsystem to dynamically adjust - the property values over time. - - - - Getting Started - - - The controller subsystem is contained within the - gstcontroller library. You need to include the header in - your element's source file: - - -... -#include <gst/gst.h> -#include <gst/controller/gstcontroller.h> -... - - - - Even though the gstcontroller library may be linked into - the host application, you should make sure it is initialized in your - plugin_init function: - - - static gboolean - plugin_init (GstPlugin *plugin) - { - ... - /* initialize library */ - gst_controller_init (NULL, NULL); - ... - } - - - It makes no sense for all GObject parameter to be real-time controlled. - Therefore the next step is to mark controllable parameters. - This is done by using the special flag GST_PARAM_CONTROLLABLE. - when setting up GObject params in the _class_init method. - - - g_object_class_install_property (gobject_class, PROP_FREQ, - g_param_spec_double ("freq", "Frequency", "Frequency of test signal", - 0.0, 20000.0, 440.0, - G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - - - - - - The Data Processing Loop - - - In the last section we learned how to mark GObject params as controllable. - Application developers can then queue parameter changes for these parameters. - The approach the controller subsystem takes is to make plugins responsible - for pulling the changes in. This requires just one action: - - - gst_object_sync_values(element,timestamp); - - - This call makes all parameter-changes for the given timestamp active by - adjusting the GObject properties of the element. Its up to the element to - determine the synchronisation rate. - - - - The Data Processing Loop for Video Elements - - For video processing elements it is the best to synchronise for every frame. - That means one would add the gst_object_sync_values() - call described in the previous section to the data processing function of - the element. - - - - - The Data Processing Loop for Audio Elements - - For audio processing elements the case is not as easy as for video - processing elements. The problem here is that audio has a much higher rate. - For PAL video one will e.g. process 25 full frames per second, but for - standard audio it will be 44100 samples. - It is rarely useful to synchronise controllable parameters that often. - The easiest solution is also to have just one synchronisation call per - buffer processing. This makes the control-rate depend on the buffer - size. - - - Elements that need a specific control-rate need to break their data - processing loop to synchronise every n-samples. - - - - diff --git a/docs/pwg/advanced-events.xml b/docs/pwg/advanced-events.xml deleted file mode 100644 index 5471ace1e6..0000000000 --- a/docs/pwg/advanced-events.xml +++ /dev/null @@ -1,442 +0,0 @@ - - Events: Seeking, Navigation and More - - There are many different event types but only two ways they can travel in - the pipeline: downstream or upstream. It is very important to understand - how both of these methods work because if one element in the pipeline is not - handling them correctly the whole event system of the pipeline is broken. - We will try to explain here how these methods work and how elements are - supposed to implement them. - - - Downstream events - - Downstream events are received through the sink pad's event handler, - as set using gst_pad_set_event_function () when - the pad was created. - - - Downstream events can travel in two ways: they can be in-band (serialised - with the buffer flow) or out-of-band (travelling through the pipeline - instantly, possibly not in the same thread as the streaming thread that - is processing the buffers, skipping ahead of buffers being processed - or queued in the pipeline). The most common downstream events - (SEGMENT, CAPS, TAG, EOS) are all serialised with the buffer flow. - - - Here is a typical event function: - - -static gboolean -gst_my_filter_sink_event (GstPad *pad, GstObject * parent, GstEvent * event) -{ - GstMyFilter *filter; - gboolean ret; - - filter = GST_MY_FILTER (parent); - ... - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - /* maybe save and/or update the current segment (e.g. for output - * clipping) or convert the event into one in a different format - * (e.g. BYTES to TIME) or drop it and set a flag to send a segment - * event in a different format later */ - ret = gst_pad_push_event (filter->src_pad, event); - break; - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - ret = gst_pad_push_event (filter->src_pad, event); - break; - case GST_EVENT_FLUSH_STOP: - gst_my_filter_clear_temporary_buffers (filter); - ret = gst_pad_push_event (filter->src_pad, event); - break; - default: - ret = gst_pad_event_default (pad, parent, event); - break; - } - - ... - return ret; -} - - - If your element is chain-based, you will almost always have to implement - a sink event function, since that is how you are notified about - segments, caps and the end of the stream. - - - If your element is exclusively loop-based, you may or may not want a - sink event function (since the element is driving the pipeline it will - know the length of the stream in advance or be notified by the flow - return value of gst_pad_pull_range(). In some cases - even loop-based element may receive events from upstream though (for - example audio decoders with an id3demux or apedemux element in front of - them, or demuxers that are being fed input from sources that send - additional information about the stream in custom events, as DVD sources - do). - - - - Upstream events - - Upstream events are generated by an element somewhere downstream in - the pipeline (example: a video sink may generate navigation - events that informs upstream elements about the current position of - the mouse pointer). This may also happen indirectly on request of the - application, for example when the application executes a seek on a - pipeline this seek request will be passed on to a sink element which - will then in turn generate an upstream seek event. - - - The most common upstream events are seek events, Quality-of-Service - (QoS) and reconfigure events. - - - An upstream event can be sent using the - gst_pad_send_event function. This - function simply call the default event handler of that pad. The default - event handler of pads is gst_pad_event_default, and - it basically sends the event to the peer of the internally linked pad. - So upstream events always arrive on the src pad of your element and are - handled by the default event handler except if you override that handler - to handle it yourself. There are some specific cases where you have to - do that : - - - - - If you have multiple sink pads in your element. In that case you will - have to decide which one of the sink pads you will send the event to - (if not all of them). - - - - - If you need to handle that event locally. For example a navigation - event that you will want to convert before sending it upstream, or - a QoS event that you want to handle. - - - - - The processing you will do in that event handler does not really matter - but there are important rules you have to absolutely respect because - one broken element event handler is breaking the whole pipeline event - handling. Here they are : - - - - - Always handle events you won't handle using the default - gst_pad_event_default method. This method will - depending on the event, forward the event or drop it. - - - - - If you are generating some new event based on the one you received - don't forget to gst_event_unref the event you received. - - - - - Event handler function are supposed to return TRUE or FALSE indicating - if the event has been handled or not. Never simply return TRUE/FALSE - in that handler except if you really know that you have handled that - event. - - - - - Remember that the event handler might be called from a different - thread than the streaming thread, so make sure you use - appropriate locking everywhere. - - - - - - - All Events Together - - In this chapter follows a list of all defined events that are currently - being used, plus how they should be used/interpreted. You can check the - what type a certain event is using the GST_EVENT_TYPE macro (or if you - need a string for debugging purposes you can use GST_EVENT_TYPE_NAME). - - - In this chapter, we will discuss the following events: - - - - - - - - - - - - - - - - - For more comprehensive information about events and how they should be - used correctly in various circumstances please consult the GStreamer - design documentation. This section only gives a general overview. - - - - Stream Start - - WRITEME - - - - - Caps - - The CAPS event contains the format description of the following - buffers. See for more - information about negotiation. - - - - - Segment - - A segment event is sent downstream to announce the range of valid - timestamps in the stream and how they should be transformed into - running-time and stream-time. A segment event must always be sent - before the first buffer of data and after a flush (see above). - - - The first segment event is created by the element driving the - pipeline, like a source operating in push-mode or a demuxer/decoder - operating pull-based. This segment event then travels down the - pipeline and may be transformed on the way (a decoder, for example, - might receive a segment event in BYTES format and might transform - this into a segment event in TIMES format based on the average - bitrate). - - - Depending on the element type, the event can simply be forwarded using - gst_pad_event_default (), or it should be parsed - and a modified event should be sent on. The last is true for demuxers, - which generally have a byte-to-time conversion concept. Their input - is usually byte-based, so the incoming event will have an offset in - byte units (GST_FORMAT_BYTES), too. Elements - downstream, however, expect segment events in time units, so that - it can be used to synchronize against the pipeline clock. Therefore, - demuxers and similar elements should not forward the event, but parse - it, free it and send a segment event (in time units, - GST_FORMAT_TIME) further downstream. - - - The segment event is created using the function - gst_event_new_segment (). See the API - reference and design document for details about its parameters. - - - Elements parsing this event can use gst_event_parse_segment() - to extract the event details. Elements may find the GstSegment - API useful to keep track of the current segment (if they want to use - it for output clipping, for example). - - - - - Tag (metadata) - - Tagging events are being sent downstream to indicate the tags as parsed - from the stream data. This is currently used to preserve tags during - stream transcoding from one format to the other. Tags are discussed - extensively in . Most - elements will simply forward the event by calling - gst_pad_event_default (). - - - The tag event is created using the function - gst_event_new_tag (), but more often elements will - send a tag event downstream that will be converted into a message - on the bus by sink elements. - All of these functions require a filled-in taglist as - argument, which they will take ownership of. - - - Elements parsing this event can use the function - gst_event_parse_tag () to acquire the - taglist that the event contains. - - - - - End of Stream (EOS) - - End-of-stream events are sent if the stream that an element sends out - is finished. An element receiving this event (from upstream, so it - receives it on its sinkpad) will generally just process any buffered - data (if there is any) and then forward the event further downstream. - The gst_pad_event_default () takes care of all - this, so most elements do not need to support this event. Exceptions are - elements that explicitly need to close a resource down on EOS, and - N-to-1 elements. Note that the stream itself is not - a resource that should be closed down on EOS! Applications might seek - back to a point before EOS and continue playing again. - - - The EOS event has no properties, which makes it one of the simplest - events in &GStreamer;. It is created using the - gst_event_new_eos() function. - - - It is important to note that only elements driving the - pipeline should ever send an EOS event. If your element - is chain-based, it is not driving the pipeline. Chain-based elements - should just return GST_FLOW_EOS from their chain function at - the end of the stream (or the configured segment), the upstream - element that is driving the pipeline will then take care of - sending the EOS event (or alternatively post a SEGMENT_DONE message - on the bus depending on the mode of operation). If you are implementing - your own source element, you also do not need to ever manually send - an EOS event, you should also just return GST_FLOW_EOS in - your create or fill function (assuming your element derives from - GstBaseSrc or GstPushSrc). - - - - - Table Of Contents - - WRITEME - - - - - Gap - - WRITEME - - - - - Flush Start - - The flush start event is sent downstream (in push mode) or upstream - (in pull mode) if all buffers and caches in the pipeline should be - emptied. Queue elements will - empty their internal list of buffers when they receive this event, for - example. File sink elements (e.g. filesink) will flush - the kernel-to-disk cache (fdatasync () or - fflush ()) when they receive this event. Normally, - elements receiving this event will simply just forward it, since most - filter or filter-like elements don't have an internal cache of data. - gst_pad_event_default () does just that, so for - most elements, it is enough to forward the event using the default - event handler. - - - As a side-effect of flushing all data from the pipeline, this event - unblocks the streaming thread by making all pads reject data until - they receive a signal - (elements trying to push data will get a FLUSHING flow return - and stop processing data). - - - The flush-start event is created with the - gst_event_new_flush_start (). - Like the EOS event, it has no properties. This event is usually - only created by elements driving the pipeline, like source elements - operating in push-mode or pull-range based demuxers/decoders. - - - - - Flush Stop - - The flush-stop event is sent by an element driving the pipeline - after a flush-start and tells pads and elements downstream that - they should accept events and buffers again (there will be at - least a SEGMENT event before any buffers first though). - - - If your element keeps temporary caches of stream data, it should - clear them when it receives a FLUSH-STOP event (and also whenever - its chain function receives a buffer with the DISCONT flag set). - - - The flush-stop event is created with - gst_event_new_flush_stop (). It has one - parameter that controls if the running-time of the pipeline should - be reset to 0 or not. Normally after a flushing seek, the - running_time is set back to 0. - - - - - Quality Of Service (QOS) - - The QOS event contains a report about the current real-time - performance of the stream. See more info in - . - - - - - Seek Request - - Seek events are meant to request a new stream position to elements. - This new position can be set in several formats (time, bytes or - default units [a term indicating frames for video, - channel-independent samples for audio, etc.]). Seeking can be done with - respect to the end-of-file or start-of-file, and - usually happens in upstream direction (downstream seeking is done by - sending a SEGMENT event with the appropriate offsets for elements - that support that, like filesink). - - - Elements receiving seek events should, depending on the element type, - either just forward it upstream (filters, decoders), change the - format in which the event is given and then forward it (demuxers), - or handle the event by changing the file pointer in their internal - stream resource (file sources, demuxers/decoders driving the pipeline - in pull-mode) or something else. - - - Seek events are built up using positions in specified formats (time, - bytes, units). They are created using the function - gst_event_new_seek (). Note that many plugins do - not support seeking from the end of the stream. - An element not driving the pipeline and forwarding a seek - request should not assume that the seek succeeded or actually happened, - it should operate based on the SEGMENT events it receives. - - - Elements parsing this event can do this using - gst_event_parse_seek(). - - - - - Navigation - - Navigation events are sent upstream by video sinks to inform upstream - elements of where the mouse pointer is, if and where mouse pointer - clicks have happened, or if keys have been pressed or released. - - - All this information is contained in the event structure which can - be obtained with gst_event_get_structure (). - - - Check out the navigationtest element in gst-plugins-good for an idea - how to extract navigation information from this event. - - - - - diff --git a/docs/pwg/advanced-interfaces.xml b/docs/pwg/advanced-interfaces.xml deleted file mode 100644 index 7be34b6787..0000000000 --- a/docs/pwg/advanced-interfaces.xml +++ /dev/null @@ -1,237 +0,0 @@ - - Interfaces - - Previously, in the chapter , we have - introduced the concept of GObject properties of controlling an element's - behaviour. This is very powerful, but it has two big disadvantages: - first of all, it is too generic, and second, it isn't dynamic. - - - The first disadvantage is related to the customizability of the end-user - interface that will be built to control the element. Some properties are - more important than others. Some integer properties are better shown in a - spin-button widget, whereas others would be better represented by a slider - widget. Such things are not possible because the UI has no actual meaning - in the application. A UI widget that represents a bitrate property is the - same as a UI widget that represents the size of a video, as long as both - are of the same GParamSpec type. Another problem, - is that things like parameter grouping, function grouping, or parameter - coupling are not - really possible. - - - The second problem with parameters are that they are not dynamic. In - many cases, the allowed values for a property are not fixed, but depend - on things that can only be detected at runtime. The names of inputs for - a TV card in a video4linux source element, for example, can only be - retrieved from the kernel driver when we've opened the device; this only - happens when the element goes into the READY state. This means that we - cannot create an enum property type to show this to the user. - - - The solution to those problems is to create very specialized types of - controls for certain often-used controls. We use the concept of interfaces - to achieve this. The basis of this all is the glib - GTypeInterface type. For each case where we think - it's useful, we've created interfaces which can be implemented by elements - at their own will. - - - One important note: interfaces do not replace - properties. Rather, interfaces should be built next to - properties. There are two important reasons for this. First of all, - properties can be more easily introspected. Second, properties can be - specified on the commandline (gst-launch). - - - - How to Implement Interfaces - - Implementing interfaces is initiated in the _get_type () - of your element. You can register one or more interfaces after having - registered the type itself. Some interfaces have dependencies on other - interfaces or can only be registered by certain types of elements. You - will be notified of doing that wrongly when using the element: it will - quit with failed assertions, which will explain what went wrong. - If it does, you need to register support for that - interface before registering support for the interface that you're - wanting to support. The example below explains how to add support for a - simple interface with no further dependencies. - - -static void gst_my_filter_some_interface_init (GstSomeInterface *iface); - -GType -gst_my_filter_get_type (void) -{ - static GType my_filter_type = 0; - - if (!my_filter_type) { - static const GTypeInfo my_filter_info = { - sizeof (GstMyFilterClass), - NULL, - NULL, - (GClassInitFunc) gst_my_filter_class_init, - NULL, - NULL, - sizeof (GstMyFilter), - 0, - (GInstanceInitFunc) gst_my_filter_init - }; - static const GInterfaceInfo some_interface_info = { - (GInterfaceInitFunc) gst_my_filter_some_interface_init, - NULL, - NULL - }; - - my_filter_type = - g_type_register_static (GST_TYPE_ELEMENT, - "GstMyFilter", - &my_filter_info, 0); - g_type_add_interface_static (my_filter_type, - GST_TYPE_SOME_INTERFACE, - &some_interface_info); - } - - return my_filter_type; -} - -static void -gst_my_filter_some_interface_init (GstSomeInterface *iface) -{ - /* here, you would set virtual function pointers in the interface */ -} - - - Or more conveniently: - - -static void gst_my_filter_some_interface_init (GstSomeInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (GstMyFilter, gst_my_filter,GST_TYPE_ELEMENT, - G_IMPLEMENT_INTERFACE (GST_TYPE_SOME_INTERFACE, - gst_my_filter_some_interface_init)); - - - - - - URI interface - - WRITEME - - - - - Color Balance Interface - - WRITEME - - - - - Video Overlay Interface - - The #GstVideoOverlay interface is used for 2 main purposes : - - - - To get a grab on the Window where the video sink element is going to render. - This is achieved by either being informed about the Window identifier that - the video sink element generated, or by forcing the video sink element to use - a specific Window identifier for rendering. - - - - - To force a redrawing of the latest video frame the video sink element - displayed on the Window. Indeed if the #GstPipeline is in #GST_STATE_PAUSED - state, moving the Window around will damage its content. Application - developers will want to handle the Expose events themselves and force the - video sink element to refresh the Window's content. - - - - - - A plugin drawing video output in a video window will need to have that - window at one stage or another. Passive mode simply means that no window - has been given to the plugin before that stage, so the plugin created the - window by itself. In that case the plugin is responsible of destroying - that window when it's not needed any more and it has to tell the - applications that a window has been created so that the application can - use it. This is done using the have-window-handle - message that can be posted from the plugin with the - gst_video_overlay_got_window_handle method. - - - As you probably guessed already active mode just means sending a video - window to the plugin so that video output goes there. This is done using - the gst_video_overlay_set_window_handle method. - - - It is possible to switch from one mode to another at any moment, so the - plugin implementing this interface has to handle all cases. There are only - 2 methods that plugins writers have to implement and they most probably - look like that : - - window) - gst_my_filter_destroy_window (my_filter->window); - - my_filter->window = handle; -} - -static void -gst_my_filter_xoverlay_init (GstVideoOverlayClass *iface) -{ - iface->set_window_handle = gst_my_filter_set_window_handle; -} - ]]> - - You will also need to use the interface methods to post messages when - needed such as when receiving a CAPS event where you will know the video - geometry and maybe create the window. - - win); -} - -/* called from the event handler for CAPS events */ -static gboolean -gst_my_filter_sink_set_caps (GstMyFilter *my_filter, GstCaps *caps) -{ - gint width, height; - gboolean ret; - ... - ret = gst_structure_get_int (structure, "width", &width); - ret &= gst_structure_get_int (structure, "height", &height); - if (!ret) return FALSE; - - gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (my_filter)); - - if (!my_filter->window) - my_filter->window = gst_my_filter_create_window (my_filter, width, height); - - ... -} - ]]> - - - - Navigation Interface - - WRITEME - - - diff --git a/docs/pwg/advanced-negotiation.xml b/docs/pwg/advanced-negotiation.xml deleted file mode 100644 index 16591d3013..0000000000 --- a/docs/pwg/advanced-negotiation.xml +++ /dev/null @@ -1,601 +0,0 @@ - - Caps negotiation - - Caps negotiation is the act of finding a media format (GstCaps) between - elements that they can handle. This process in &GStreamer; can in most - cases find an optimal solution for the complete pipeline. In this section - we explain how this works. - - - - Caps negotiation basics - - In &GStreamer;, negotiation of the media format always follows the - following simple rules: - - - - - A downstream element suggest a format on its sinkpad and places the - suggestion in the result of the CAPS query performed on the sinkpad. - See also . - - - - - An upstream element decides on a format. It sends the selected media - format downstream on its source pad with a CAPS event. Downstream - elements reconfigure themselves to handle the media type in the CAPS - event on the sinkpad. - - - - - A downstream element can inform upstream that it would like to - suggest a new format by sending a RECONFIGURE event upstream. The - RECONFIGURE event simply instructs an upstream element to restart - the negotiation phase. Because the element that sent out the - RECONFIGURE event is now suggesting another format, the format - in the pipeline might change. - - - - - In addition to the CAPS and RECONFIGURE event and the CAPS query, there - is an ACCEPT_CAPS query to quickly check if a certain caps can - be accepted by an element. - - - All negotiation follows these simple rules. Let's take a look at some - typical uses cases and how negotiation happens. - - - - - Caps negotiation use cases - - In what follows we will look at some use cases for push-mode scheduling. - The pull-mode scheduling negotiation phase is discussed in - and is actually similar as we - will see. - - - Since the sink pads only suggest formats and the source pads need to - decide, the most complicated work is done in the source pads. - We can identify 3 caps negotiation use cases for the source pads: - - - - - Fixed negotiation. An element can output one format only. - See . - - - - - Transform negotiation. There is a (fixed) transform between the - input and output format of the element, usually based on some - element property. The caps that the element will produce depend - on the upstream caps and the caps that the element can accept - depend on the downstream caps. - See . - - - - - Dynamic negotiation. An element can output many formats. - See . - - - - - - Fixed negotiation - - In this case, the source pad can only produce a fixed format. Usually - this format is encoded inside the media. No downstream element can - ask for a different format, the only way that the source pad will - renegotiate is when the element decides to change the caps itself. - - - Elements that could implement fixed caps (on their source pads) are, - in general, all elements that are not renegotiable. Examples include: - - - - - A typefinder, since the type found is part of the actual data stream - and can thus not be re-negotiated. The typefinder will look at the - stream of bytes, figure out the type, send a CAPS event with the - caps and then push buffers of the type. - - - - - Pretty much all demuxers, since the contained elementary data - streams are defined in the file headers, and thus not - renegotiable. - - - - - Some decoders, where the format is embedded in the data stream - and not part of the peercaps and where the - decoder itself is not reconfigurable, too. - - - - - Some sources that produce a fixed format. - - - - - gst_pad_use_fixed_caps() is used on the source - pad with fixed caps. As long as the pad is not negotiated, the default - CAPS query will return the caps presented in the padtemplate. As soon - as the pad is negotiated, the CAPS query will return the negotiated - caps (and nothing else). These are the relevant code snippets for fixed - caps source pads. - - - - - - The fixed caps can then be set on the pad by calling - gst_pad_set_caps (). - - -, - "channels", G_TYPE_INT, , NULL); - if (!gst_pad_set_caps (pad, caps)) { - GST_ELEMENT_ERROR (element, CORE, NEGOTIATION, (NULL), - ("Some debug information here")); - return GST_FLOW_ERROR; - } -[..] -]]> - - - These types of elements also don't have a relation between the input - format and the output format, the input caps simply don't contain the - information needed to produce the output caps. - - - All other elements that need to be configured for the format should - implement full caps negotiation, which will be explained in the next - few sections. - - - - - Transform negotiation - - In this negotiation technique, there is a fixed transform between - the element input caps and the output caps. This transformation - could be parameterized by element properties but not by the - content of the stream (see - for that use-case). - - - The caps that the element can accept depend on the (fixed - transformation) downstream caps. The caps that the element can - produce depend on the (fixed transformation of) the upstream - caps. - - - This type of element can usually set caps on its source pad from - the _event() function on the sink pad when - it received the CAPS event. This means that the caps transform - function transforms a fixed caps into another fixed caps. - Examples of elements include: - - - - - Videobox. It adds configurable border around a video frame - depending on object properties. - - - - - Identity elements. All elements that don't change the format - of the data, only the content. Video and audio effects are an - example. Other examples include elements that inspect the - stream. - - - - - Some decoders and encoders, where the output format is defined - by input format, like mulawdec and mulawenc. These decoders - usually have no headers that define the content of the stream. - They are usually more like conversion elements. - - - - - Below is an example of a negotiation steps of a typical transform - element. In the sink pad CAPS event handler, we compute the caps - for the source pad and set those. - - -srcpad, outcaps); - gst_caps_unref (outcaps); - - return ret; -} - -static gboolean -gst_my_filter_sink_event (GstPad *pad, - GstObject *parent, - GstEvent *event) -{ - gboolean ret; - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - ret = gst_my_filter_setcaps (filter, caps); - break; - } - default: - ret = gst_pad_event_default (pad, parent, event); - break; - } - return ret; -} - - [...] -]]> - - - - - Dynamic negotiation - - A last negotiation method is the most complex and powerful dynamic - negotiation. - - - Like with the transform negotiation in - , dynamic negotiation will - perform a transformation on the downstream/upstream caps. Unlike the - transform negotiation, this transform will convert fixed caps to - unfixed caps. This means that the sink pad input caps can be converted - into unfixed (multiple) formats. The source pad will have to choose a - format from all the possibilities. It would usually like to choose a - format that requires the least amount of effort to produce but it does - not have to be. The selection of the format should also depend on the - caps that can be accepted downstream (see a QUERY_CAPS function in - ). - - - A typical flow goes like this: - - - - - Caps are received on the sink pad of the element. - - - - - If the element prefers to operate in passthrough mode, check - if downstream accepts the caps with the ACCEPT_CAPS query. If it - does, we can complete negotiation and we can operate in - passthrough mode. - - - - - Calculate the possible caps for the source pad. - - - - - Query the downstream peer pad for the list of possible - caps. - - - - - Select from the downstream list the first caps that you can - transform to and set this as the output caps. You might have to - fixate the caps to some reasonable defaults to construct - fixed caps. - - - - - Examples of this type of elements include: - - - - - Converter elements such as videoconvert, audioconvert, audioresample, - videoscale, ... - - - - - Source elements such as audiotestsrc, videotestsrc, v4l2src, - pulsesrc, ... - - - - - Let's look at the example of an element that can convert between - samplerates, so where input and output samplerate don't have to be - the same: - - -srcpad, caps)) { - filter->passthrough = TRUE; - } else { - GstCaps *othercaps, *newcaps; - GstStructure *s = gst_caps_get_structure (caps, 0), *others; - - /* no passthrough, setup internal conversion */ - gst_structure_get_int (s, "channels", &filter->channels); - othercaps = gst_pad_get_allowed_caps (filter->srcpad); - others = gst_caps_get_structure (othercaps, 0); - gst_structure_set (others, - "channels", G_TYPE_INT, filter->channels, NULL); - - /* now, the samplerate value can optionally have multiple values, so - * we "fixate" it, which means that one fixed value is chosen */ - newcaps = gst_caps_copy_nth (othercaps, 0); - gst_caps_unref (othercaps); - gst_pad_fixate_caps (filter->srcpad, newcaps); - if (!gst_pad_set_caps (filter->srcpad, newcaps)) - return FALSE; - - /* we are now set up, configure internally */ - filter->passthrough = FALSE; - gst_structure_get_int (s, "rate", &filter->from_samplerate); - others = gst_caps_get_structure (newcaps, 0); - gst_structure_get_int (others, "rate", &filter->to_samplerate); - } - - return TRUE; -} - -static gboolean -gst_my_filter_sink_event (GstPad *pad, - GstObject *parent, - GstEvent *event) -{ - gboolean ret; - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - ret = gst_my_filter_setcaps (filter, caps); - break; - } - default: - ret = gst_pad_event_default (pad, parent, event); - break; - } - return ret; -} - -static GstFlowReturn -gst_my_filter_chain (GstPad *pad, - GstObject *parent, - GstBuffer *buf) -{ - GstMyFilter *filter = GST_MY_FILTER (parent); - GstBuffer *out; - - /* push on if in passthrough mode */ - if (filter->passthrough) - return gst_pad_push (filter->srcpad, buf); - - /* convert, push */ - out = gst_my_filter_convert (filter, buf); - gst_buffer_unref (buf); - - return gst_pad_push (filter->srcpad, out); -} -]]> - - - - - - Upstream caps (re)negotiation - - Upstream negotiation's primary use is to renegotiate (part of) an - already-negotiated pipeline to a new format. Some practical examples - include to select a different video size because the size of the video - window changed, and the video output itself is not capable of rescaling, - or because the audio channel configuration changed. - - - Upstream caps renegotiation is requested by sending a GST_EVENT_RECONFIGURE - event upstream. The idea is that it will instruct the upstream element - to reconfigure its caps by doing a new query for the allowed caps and then - choosing a new caps. The element that sends out the RECONFIGURE event - would influence the selection of the new caps by returning the new - preferred caps from its GST_QUERY_CAPS query function. The RECONFIGURE - event will set the GST_PAD_FLAG_NEED_RECONFIGURE on all pads that it - travels over. - - - It is important to note here that different elements actually have - different responsibilities here: - - - - - Elements that want to propose a new format upstream need to first - check if the new caps are acceptable upstream with an ACCEPT_CAPS - query. Then they would send a RECONFIGURE event and be prepared to - answer the CAPS query with the new preferred format. It should be - noted that when there is no upstream element that can (or wants) - to renegotiate, the element needs to deal with the currently - configured format. - - - - - Elements that operate in transform negotiation according to - pass the RECONFIGURE - event upstream. Because these elements simply do a fixed transform - based on the upstream caps, they need to send the event upstream - so that it can select a new format. - - - - - Elements that operate in fixed negotiation - () drop the RECONFIGURE event. - These elements can't reconfigure and their output caps don't depend - on the upstream caps so the event can be dropped. - - - - - Elements that can be reconfigured on the source pad (source pads - implementing dynamic negotiation in - ) should check its - NEED_RECONFIGURE flag with - gst_pad_check_reconfigure () and it should - start renegotiation when the function returns TRUE. - - - - - - - Implementing a CAPS query function - - A _query ()-function with the GST_QUERY_CAPS query - type is called when a peer element would like to know which formats - this pad supports, and in what order of preference. The return value - should be all formats that this elements supports, taking into account - limitations of peer elements further downstream or upstream, sorted by - order of preference, highest preference first. - - - - -srcpad) ? filter->sinkpad : - filter->srcpad; - caps = gst_pad_get_allowed_caps (otherpad); - - gst_query_parse_caps (query, &filt); - - /* We support *any* samplerate, indifferent from the samplerate - * supported by the linked elements on both sides. */ - for (i = 0; i < gst_caps_get_size (caps); i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); - - gst_structure_remove_field (structure, "rate"); - } - - /* make sure we only return results that intersect our - * padtemplate */ - tcaps = gst_pad_get_pad_template_caps (pad); - if (tcaps) { - temp = gst_caps_intersect (caps, tcaps); - gst_caps_unref (caps); - gst_caps_unref (tcaps); - caps = temp; - } - /* filter against the query filter when needed */ - if (filt) { - temp = gst_caps_intersect (caps, filt); - gst_caps_unref (caps); - caps = temp; - } - gst_query_set_caps_result (query, caps); - gst_caps_unref (caps); - ret = TRUE; - break; - } - default: - ret = gst_pad_query_default (pad, parent, query); - break; - } - return ret; -} -]]> - - - - - Pull-mode Caps negotiation - - WRITEME, the mechanism of pull-mode negotiation is not yet fully - understood. - - - - Using all the knowledge you've acquired by reading this chapter, you - should be able to write an element that does correct caps negotiation. - If in doubt, look at other elements of the same type in our git - repository to get an idea of how they do what you want to do. - - - diff --git a/docs/pwg/advanced-qos.xml b/docs/pwg/advanced-qos.xml deleted file mode 100644 index b87bf1e812..0000000000 --- a/docs/pwg/advanced-qos.xml +++ /dev/null @@ -1,283 +0,0 @@ - - Quality Of Service (QoS) - - - Quality of Service in &GStreamer; is about measuring and adjusting - the real-time performance of a pipeline. The real-time performance is - always measured relative to the pipeline clock and typically happens in - the sinks when they synchronize buffers against the clock. - - - When buffers arrive late in the sink, i.e. when their running-time is - smaller than that of the clock, we say that the pipeline is having a - quality of service problem. These are a few possible reasons: - - - - - High CPU load, there is not enough CPU power to handle the stream, - causing buffers to arrive late in the sink. - - - - - Network problems - - - - - Other resource problems such as disk load, memory bottlenecks etc - - - - - The measurements result in QOS events that aim to adjust the datarate - in one or more upstream elements. Two types of adjustments can be - made: - - - - - Short time "emergency" corrections based on latest observation in - the sinks. - - - Long term rate corrections based on trends observed in the sinks. - - - - - It is also possible for the application to artificially introduce delay - between synchronized buffers, this is called throttling. It can be used - to limit or reduce the framerate, for example. - - - - Measuring QoS - - Elements that synchronize buffers on the pipeline clock will usually - measure the current QoS. They will also need to keep some statistics - in order to generate the QOS event. - - - For each buffer that arrives in the sink, the element needs to calculate - how late or how early it was. This is called the jitter. Negative jitter - values mean that the buffer was early, positive values mean that the - buffer was late. the jitter value gives an indication of how early/late - a buffer was. - - - A synchronizing element will also need to calculate how much time - elapsed between receiving two consecutive buffers. We call this the - processing time because that is the amount of time it takes for the - upstream element to produce/process the buffer. We can compare this - processing time to the duration of the buffer to have a measurement - of how fast upstream can produce data, called the proportion. - If, for example, upstream can produce a buffer in 0.5 seconds of 1 - second long, it is operating at twice the required speed. If, on the - other hand, it takes 2 seconds to produce a buffer with 1 seconds worth - of data, upstream is producing buffers too slow and we won't be able to - keep synchronization. Usually, a running average is kept of the - proportion. - - - A synchronizing element also needs to measure its own performance in - order to figure out if the performance problem is upstream of itself. - - - These measurements are used to construct a QOS event that is sent - upstream. Note that a QoS event is sent for each buffer that arrives - in the sink. - - - - - Handling QoS - - An element will have to install an event function on its source pads - in order to receive QOS events. Usually, the element will need to - store the value of the QOS event and use them in the data processing - function. The element will need to use a lock to protect these QoS - values as shown in the example below. Also make sure to pass the - QoS event upstream. - - -qos_proportion = proportion; - priv->qos_timestamp = timestamp; - priv->qos_diff = diff; - GST_OBJECT_UNLOCK (decoder); - - res = gst_pad_push_event (decoder->sinkpad, event); - break; - } - - [...] -]]> - - - With the QoS values, there are two types of corrections that an element - can do: - - - - Short term correction - - The timestamp and the jitter value in the QOS event can be used to - perform a short term correction. If the jitter is positive, the - previous buffer arrived late and we can be sure that a buffer with - a timestamp < timestamp + jitter is also going to be late. We - can thus drop all buffers with a timestamp less than timestamp + - jitter. - - - If the buffer duration is known, a better estimation for the next - likely timestamp as: timestamp + 2 * jitter + duration. - - - A possible algorithm typically looks like this: - - -qos_proportion; - qos_timestamp = priv->qos_timestamp; - qos_diff = priv->qos_diff; - GST_OBJECT_UNLOCK (dec); - - /* calculate the earliest valid timestamp */ - if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (qos_timestamp))) { - if (G_UNLIKELY (qos_diff > 0)) { - earliest_time = qos_timestamp + 2 * qos_diff + frame_duration; - } else { - earliest_time = qos_timestamp + qos_diff; - } - } else { - earliest_time = GST_CLOCK_TIME_NONE; - } - - /* compare earliest_time to running-time of next buffer */ - if (earliest_time > timestamp) - goto drop_buffer; - - [...] -]]> - - - - - Long term correction - - Long term corrections are a bit more difficult to perform. They - rely on the value of the proportion in the QOS event. Elements should - reduce the amount of resources they consume by the proportion - field in the QoS message. - - - Here are some possible strategies to achieve this: - - - - - Permanently dropping frames or reducing the CPU or bandwidth - requirements of the element. Some decoders might be able to - skip decoding of B frames. - - - - - Switch to lower quality processing or reduce the algorithmic - complexity. Care should be taken that this doesn't introduce - disturbing visual or audible glitches. - - - - - Switch to a lower quality source to reduce network bandwidth. - - - - - Assign more CPU cycles to critical parts of the pipeline. This - could, for example, be done by increasing the thread priority. - - - - - In all cases, elements should be prepared to go back to their normal - processing rate when the proportion member in the QOS event approaches - the ideal proportion of 1.0 again. - - - - - - Throttling - - Elements synchronizing to the clock should expose a property to configure - them in throttle mode. In throttle mode, the time distance between buffers - is kept to a configurable throttle interval. This means that effectively - the buffer rate is limited to 1 buffer per throttle interval. This can be - used to limit the framerate, for example. - - - When an element is configured in throttling mode (this is usually only - implemented on sinks) it should produce QoS events upstream with the jitter - field set to the throttle interval. This should instruct upstream elements to - skip or drop the remaining buffers in the configured throttle interval. - - - The proportion field is set to the desired slowdown needed to get the - desired throttle interval. Implementations can use the QoS Throttle type, - the proportion and the jitter member to tune their implementations. - - - The default sink base class, has the throttle-time - property for this feature. You can test this with: - gst-launch-1.0 videotestsrc ! - xvimagesink throttle-time=500000000 - - - - - QoS Messages - - In addition to the QOS events that are sent between elements in the - pipeline, there are also QOS messages posted on the pipeline bus to - inform the application of QoS decisions. The QOS message contains - the timestamps of when something was dropped along with the amount - of dropped vs processed items. Elements must post a QOS - message under these conditions: - - - - - The element dropped a buffer because of QoS reasons. - - - - - An element changes its processing strategy because of QoS reasons - (quality). This could include a decoder that decides to drop every - B frame to increase its processing speed or an effect element - switching to a lower quality algorithm. - - - - - - diff --git a/docs/pwg/advanced-request.xml b/docs/pwg/advanced-request.xml deleted file mode 100644 index 8ef98977c6..0000000000 --- a/docs/pwg/advanced-request.xml +++ /dev/null @@ -1,290 +0,0 @@ - - Request and Sometimes pads - - Until now, we've only dealt with pads that are always available. However, - there's also pads that are only being created in some cases, or only if - the application requests the pad. The first is called a - sometimes; the second is called a - request pad. The availability of a pad (always, - sometimes or request) can be seen in a pad's template. This chapter will - discuss when each of the two is useful, how they are created and when - they should be disposed. - - - - Sometimes pads - - A sometimes pad is a pad that is created under certain - conditions, but not in all cases. This mostly depends on stream content: - demuxers will generally parse the stream header, decide what elementary - (video, audio, subtitle, etc.) streams are embedded inside the system - stream, and will then create a sometimes pad for each of those elementary - streams. At its own choice, it can also create more than one instance of - each of those per element instance. The only limitation is that each - newly created pad should have a unique name. Sometimes pads are disposed - when the stream data is disposed, too (i.e. when going from PAUSED to the - READY state). You should not dispose the pad on EOS, - because someone might re-activate the pipeline and seek back to before - the end-of-stream point. The stream should still stay valid after EOS, at - least until the stream data is disposed. In any case, the element is - always the owner of such a pad. - - - The example code below will parse a text file, where the first line is - a number (n). The next lines all start with a number (0 to n-1), which - is the number of the source pad over which the data should be sent. - - -3 -0: foo -1: bar -0: boo -2: bye - - - The code to parse this file and create the dynamic sometimes - pads, looks like this: - - -firstrun = TRUE; - filter->srcpadlist = NULL; -} - -/* - * Get one line of data - without newline. - */ - -static GstBuffer * -gst_my_filter_getline (GstMyFilter *filter) -{ - guint8 *data; - gint n, num; - - /* max. line length is 512 characters - for safety */ - for (n = 0; n < 512; n++) { - num = gst_bytestream_peek_bytes (filter->bs, &data, n + 1); - if (num != n + 1) - return NULL; - - /* newline? */ - if (data[n] == '\n') { - GstBuffer *buf = gst_buffer_new_allocate (NULL, n + 1, NULL); - - gst_bytestream_peek_bytes (filter->bs, &data, n); - gst_buffer_fill (buf, 0, data, n); - gst_buffer_memset (buf, n, '\0', 1); - gst_bytestream_flush_fast (filter->bs, n + 1); - - return buf; - } - } -} - -static void -gst_my_filter_loopfunc (GstElement *element) -{ - GstMyFilter *filter = GST_MY_FILTER (element); - GstBuffer *buf; - GstPad *pad; - GstMapInfo map; - gint num, n; - - /* parse header */ - if (filter->firstrun) { - gchar *padname; - guint8 id; - - if (!(buf = gst_my_filter_getline (filter))) { - gst_element_error (element, STREAM, READ, (NULL), - ("Stream contains no header")); - return; - } - gst_buffer_extract (buf, 0, &id, 1); - num = atoi (id); - gst_buffer_unref (buf); - - /* for each of the streams, create a pad */ - for (n = 0; n < num; n++) { - padname = g_strdup_printf ("src_%u", n); - pad = gst_pad_new_from_static_template (src_factory, padname); - g_free (padname); - - /* here, you would set _event () and _query () functions */ - - /* need to activate the pad before adding */ - gst_pad_set_active (pad, TRUE); - - gst_element_add_pad (element, pad); - filter->srcpadlist = g_list_append (filter->srcpadlist, pad); - } - } - - /* and now, simply parse each line and push over */ - if (!(buf = gst_my_filter_getline (filter))) { - GstEvent *event = gst_event_new (GST_EVENT_EOS); - GList *padlist; - - for (padlist = srcpadlist; - padlist != NULL; padlist = g_list_next (padlist)) { - pad = GST_PAD (padlist->data); - gst_pad_push_event (pad, gst_event_ref (event)); - } - gst_event_unref (event); - /* pause the task here */ - return; - } - - /* parse stream number and go beyond the ':' in the data */ - gst_buffer_map (buf, &map, GST_MAP_READ); - num = atoi (map.data[0]); - if (num >= 0 && num < g_list_length (filter->srcpadlist)) { - pad = GST_PAD (g_list_nth_data (filter->srcpadlist, num); - - /* magic buffer parsing foo */ - for (n = 0; map.data[n] != ':' && - map.data[n] != '\0'; n++) ; - if (map.data[n] != '\0') { - GstBuffer *sub; - - /* create region copy that starts right past the space. The reason - * that we don't just forward the data pointer is because the - * pointer is no longer the start of an allocated block of memory, - * but just a pointer to a position somewhere in the middle of it. - * That cannot be freed upon disposal, so we'd either crash or have - * a memleak. Creating a region copy is a simple way to solve that. */ - sub = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, - n + 1, map.size - n - 1); - gst_pad_push (pad, sub); - } - } - gst_buffer_unmap (buf, &map); - gst_buffer_unref (buf); -} -]]> - - - Note that we use a lot of checks everywhere to make sure that the content - in the file is valid. This has two purposes: first, the file could be - erroneous, in which case we prevent a crash. The second and most important - reason is that - in extreme cases - the file could be used maliciously to - cause undefined behaviour in the plugin, which might lead to security - issues. Always assume that the file could be used to - do bad things. - - - - - Request pads - - Request pads are similar to sometimes pads, except that - request are created on demand of something outside of the element rather - than something inside the element. This concept is often used in muxers, - where - for each elementary stream that is to be placed in the output - system stream - one sink pad will be requested. It can also be used in - elements with a variable number of input or outputs pads, such as the - tee (multi-output) or - input-selector (multi-input) elements. - - - To implement request pads, you need to provide a padtemplate with a - GST_PAD_REQUEST presence and implement the - request_new_pad virtual method in - GstElement. - To clean up, you will need to implement the - release_pad virtual method. - - -request_new_pad = gst_my_filter_request_new_pad; - element_class->release_pad = gst_my_filter_release_pad; -} - -static GstPad * -gst_my_filter_request_new_pad (GstElement *element, - GstPadTemplate *templ, - const gchar *name, - const GstCaps *caps) -{ - GstPad *pad; - GstMyFilterInputContext *context; - - context = g_new0 (GstMyFilterInputContext, 1); - pad = gst_pad_new_from_template (templ, name); - gst_pad_set_element_private (pad, context); - - /* normally, you would set _chain () and _event () functions here */ - - gst_element_add_pad (element, pad); - - return pad; -} - -static void -gst_my_filter_release_pad (GstElement *element, - GstPad *pad) -{ - GstMyFilterInputContext *context; - - context = gst_pad_get_element_private (pad); - g_free (context); - - gst_element_remove_pad (element, pad); -} - -]]> - - - diff --git a/docs/pwg/advanced-scheduling.xml b/docs/pwg/advanced-scheduling.xml deleted file mode 100644 index 4639d63687..0000000000 --- a/docs/pwg/advanced-scheduling.xml +++ /dev/null @@ -1,445 +0,0 @@ - - Different scheduling modes - - The scheduling mode of a pad defines how data is retrieved from (source) - or given to (sink) pads. &GStreamer; can operate in two scheduling - mode, called push- and pull-mode. &GStreamer; supports elements with pads - in any of the scheduling modes where not all pads need to be operating - in the same mode. - - - So far, we have only discussed _chain ()-operating - elements, i.e. elements that have a chain-function set on their sink pad - and push buffers on their source pad(s). We call this the push-mode - because a peer element will use gst_pad_push () on - a srcpad, which will cause our _chain ()-function - to be called, which in turn causes our element to push out a buffer on - the source pad. The initiative to start the dataflow happens somewhere - upstream when it pushes out a buffer and all downstream elements get - scheduled when their _chain ()-functions are - called in turn. - - - Before we explain pull-mode scheduling, let's first understand how the - different scheduling modes are selected and activated on a pad. - - - - The pad activation stage - - During the element state change of READY->PAUSED, the pads of an - element will be activated. This happens first on the source pads and - then on the sink pads of the element. &GStreamer; calls the - _activate () of a pad. By default this function - will activate the pad in push-mode by calling - gst_pad_activate_mode () with the GST_PAD_MODE_PUSH - scheduling mode. - It is possible to override the _activate () of a pad - and decide on a different scheduling mode. You can know in what - scheduling mode a pad is activated by overriding the - _activate_mode ()-function. - - - &GStreamer; allows the different pads of an element to operate in - different scheduling modes. This allows for many different possible - use-cases. What follows is an overview of some typical use-cases. - - - - - If all pads of an element are activated in push-mode scheduling, - the element as a whole is operating in push-mode. - For source elements this means that they will have to start a - task that pushes out buffers on the source pad to the downstream - elements. - Downstream elements will have data pushed to them by upstream elements - using the sinkpads _chain ()-function which will - push out buffers on the source pads. - Prerequisites for this scheduling mode are that a chain-function was - set for each sinkpad using gst_pad_set_chain_function () - and that all downstream elements operate in the same mode. - - - - - Alternatively, sinkpads can be the driving force behind a pipeline - by operating in pull-mode, while the sourcepads - of the element still operate in push-mode. In order to be the - driving force, those pads start a GstTask - when they are activated. This task is a thread, which - will call a function specified by the element. When called, this - function will have random data access (through - gst_pad_pull_range ()) over all sinkpads, and - can push data over the sourcepads, which effectively means that - this element controls data flow in the pipeline. Prerequisites for - this mode are that all downstream elements can act in push - mode, and that all upstream elements operate in pull-mode (see below). - - - Source pads can be activated in PULL mode by a downstream element - when they return GST_PAD_MODE_PULL from the GST_QUERY_SCHEDULING - query. Prerequisites for this scheduling mode are that a - getrange-function was set for the source pad using - gst_pad_set_getrange_function (). - - - - - Lastly, all pads in an element can be activated in PULL-mode. - However, contrary to the above, this does not mean that they - start a task on their own. Rather, it means that they are pull - slave for the downstream element, and have to provide random data - access to it from their _get_range ()-function. - Requirements are that the a _get_range - ()-function was set on this pad using the function - gst_pad_set_getrange_function (). Also, if - the element has any sinkpads, all those pads (and thereby their - peers) need to operate in PULL access mode, too. - - - When a sink element is activated in PULL mode, it should start a - task that calls gst_pad_pull_range () on its - sinkpad. It can only do this when the upstream SCHEDULING query - returns support for the GST_PAD_MODE_PULL scheduling mode. - - - - - In the next two sections, we will go closer into pull-mode scheduling - (elements/pads driving the pipeline, and elements/pads providing random - access), and some specific use cases will be given. - - - - - Pads driving the pipeline - - Sinkpads operating in pull-mode, with the sourcepads operating in - push-mode (or it has no sourcepads when it is a sink), can start a task - that will drive the pipeline data flow. - Within this task function, you have random access over all of the sinkpads, - and push data over the sourcepads. - This can come in useful for several different kinds of elements: - - - - - Demuxers, parsers and certain kinds of decoders where data comes - in unparsed (such as MPEG-audio or video streams), since those will - prefer byte-exact (random) access from their input. If possible, - however, such elements should be prepared to operate in push-mode - mode, too. - - - - - Certain kind of audio outputs, which require control over their - input data flow, such as the Jack sound server. - - - - - First you need to perform a SCHEDULING query to check if the upstream - element(s) support pull-mode scheduling. If that is possible, you - can activate the sinkpad in pull-mode. Inside the activate_mode - function you can then start the task. - - -#include "filter.h" -#include <string.h> - -static gboolean gst_my_filter_activate (GstPad * pad, - GstObject * parent); -static gboolean gst_my_filter_activate_mode (GstPad * pad, - GstObject * parent, - GstPadMode mode, - gboolean active); -static void gst_my_filter_loop (GstMyFilter * filter); - -G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); - - -static void -gst_my_filter_init (GstMyFilter * filter) -{ - -[..] - - gst_pad_set_activate_function (filter->sinkpad, gst_my_filter_activate); - gst_pad_set_activatemode_function (filter->sinkpad, - gst_my_filter_activate_mode); - - -[..] -} - -[..] - -static gboolean -gst_my_filter_activate (GstPad * pad, GstObject * parent) -{ - GstQuery *query; - gboolean pull_mode; - - /* first check what upstream scheduling is supported */ - query = gst_query_new_scheduling (); - - if (!gst_pad_peer_query (pad, query)) { - gst_query_unref (query); - goto activate_push; - } - - /* see if pull-mode is supported */ - 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 activate_push; - - /* now we can activate in pull-mode. GStreamer will also - * activate the upstream peer in pull-mode */ - return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); - -activate_push: - { - /* something not right, we fallback to push-mode */ - return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); - } -} - -static gboolean -gst_my_filter_activate_pull (GstPad * pad, - GstObject * parent, - GstPadMode mode, - gboolean active) -{ - gboolean res; - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (mode) { - case GST_PAD_MODE_PUSH: - res = TRUE; - break; - case GST_PAD_MODE_PULL: - if (active) { - filter->offset = 0; - res = gst_pad_start_task (pad, - (GstTaskFunction) gst_my_filter_loop, filter, NULL); - } else { - res = gst_pad_stop_task (pad); - } - break; - default: - /* unknown scheduling mode */ - res = FALSE; - break; - } - return res; -} - - - Once started, your task has full control over input and output. The - most simple case of a task function is one that reads input and pushes - that over its source pad. It's not all that useful, but provides some - more flexibility than the old push-mode case that we've been looking - at so far. - - -#define BLOCKSIZE 2048 - -static void -gst_my_filter_loop (GstMyFilter * filter) -{ - GstFlowReturn ret; - guint64 len; - GstFormat fmt = GST_FORMAT_BYTES; - GstBuffer *buf = NULL; - - if (!gst_pad_query_duration (filter->sinkpad, fmt, &len)) { - GST_DEBUG_OBJECT (filter, "failed to query duration, pausing"); - goto stop; - } - - if (filter->offset >= len) { - GST_DEBUG_OBJECT (filter, "at end of input, sending EOS, pausing"); - gst_pad_push_event (filter->srcpad, gst_event_new_eos ()); - goto stop; - } - - /* now, read BLOCKSIZE bytes from byte offset filter->offset */ - ret = gst_pad_pull_range (filter->sinkpad, filter->offset, - BLOCKSIZE, &buf); - - if (ret != GST_FLOW_OK) { - GST_DEBUG_OBJECT (filter, "pull_range failed: %s", gst_flow_get_name (ret)); - goto stop; - } - - /* now push buffer downstream */ - ret = gst_pad_push (filter->srcpad, buf); - - buf = NULL; /* gst_pad_push() took ownership of buffer */ - - if (ret != GST_FLOW_OK) { - GST_DEBUG_OBJECT (filter, "pad_push failed: %s", gst_flow_get_name (ret)); - goto stop; - } - - /* everything is fine, increase offset and wait for us to be called again */ - filter->offset += BLOCKSIZE; - return; - -stop: - GST_DEBUG_OBJECT (filter, "pausing task"); - gst_pad_pause_task (filter->sinkpad); -} - - - - - - Providing random access - - In the previous section, we have talked about how elements (or pads) - that are activated to drive the pipeline using their own task, must use - pull-mode scheduling on their sinkpads. This means that all pads linked - to those pads need to be activated in pull-mode. - Source pads activated in pull-mode must implement a - _get_range ()-function set using - gst_pad_set_getrange_function (), and - that function will be called when the peer pad requests some data with - gst_pad_pull_range (). - The element is then responsible for seeking to the right offset and - providing the requested data. Several elements can implement random - access: - - - - - Data sources, such as a file source, that can provide data from any - offset with reasonable low latency. - - - - - Filters that would like to provide a pull-mode scheduling - over the whole pipeline. - - - - - Parsers who can easily provide this by skipping a small part of - their input and are thus essentially "forwarding" getrange - requests literally without any own processing involved. Examples - include tag readers (e.g. ID3) or single output parsers, such as - a WAVE parser. - - - - - The following example will show how a _get_range - ()-function can be implemented in a source element: - - -#include "filter.h" -static GstFlowReturn - gst_my_filter_get_range (GstPad * pad, - GstObject * parent, - guint64 offset, - guint length, - GstBuffer ** buf); - -G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); - - - -static void -gst_my_filter_init (GstMyFilter * filter) -{ - -[..] - - gst_pad_set_getrange_function (filter->srcpad, - gst_my_filter_get_range); - -[..] -} - -static GstFlowReturn -gst_my_filter_get_range (GstPad * pad, - GstObject * parent, - guint64 offset, - guint length, - GstBuffer ** buf) -{ - - GstMyFilter *filter = GST_MY_FILTER (parent); - - [.. here, you would fill *buf ..] - - return GST_FLOW_OK; -} - - - - In practice, many elements that could theoretically do random access, - may in practice often be activated in push-mode scheduling anyway, - since there is no downstream element able to start its own task. - Therefore, in practice, those elements should implement both a - _get_range ()-function and a _chain - ()-function (for filters and parsers) or a _get_range - ()-function and be prepared to start their own task by - providing _activate_* ()-functions (for - source elements). - - - diff --git a/docs/pwg/advanced-tagging.xml b/docs/pwg/advanced-tagging.xml deleted file mode 100644 index d1e5393017..0000000000 --- a/docs/pwg/advanced-tagging.xml +++ /dev/null @@ -1,241 +0,0 @@ - - Tagging (Metadata and Streaminfo) - - - Overview - - Tags are pieces of information stored in a stream that are not the content - itself, but they rather describe the content. Most - media container formats support tagging in one way or another. Ogg uses - VorbisComment for this, MP3 uses ID3, AVI and WAV use RIFF's INFO list - chunk, etc. GStreamer provides a general way for elements to read tags from - the stream and expose this to the user. The tags (at least the metadata) - will be part of the stream inside the pipeline. The consequence of this is - that transcoding of files from one format to another will automatically - preserve tags, as long as the input and output format elements both support - tagging. - - - Tags are separated in two categories in GStreamer, even though applications - won't notice anything of this. The first are called metadata, - the second are called streaminfo. Metadata are tags - that describe the non-technical parts of stream content. They can be - changed without needing to re-encode the stream completely. Examples are - author, title or album. The - container format might still need to be re-written for the tags to fit in, - though. Streaminfo, on the other hand, are tags that describe the stream - contents technically. To change them, the stream needs to be re-encoded. - Examples are codec or bitrate. Note that some - container formats (like ID3) store various streaminfo tags as metadata in - the file container, which means that they can be changed so that they don't - match the content in the file any more. Still, they are called metadata - because technically, they can be changed without - re-encoding the whole stream, even though that makes them invalid. Files - with such metadata tags will have the same tag twice: once as metadata, - once as streaminfo. - - - There is no special name for tag reading elements in &GStreamer;. There are - specialised elements (e.g. id3demux) that do nothing besides tag reading, - but any &GStreamer; element may extract tags while processing data, and - most decoders, demuxers and parsers do. - - - A tag writer is called TagSetter. - An element supporting both can be used in a tag editor for quick tag - changing (note: in-place tag editing is still poorly supported at the time - of writing and usually requires tag extraction/stripping and remuxing of - the stream with new tags). - - - - - Reading Tags from Streams - - The basic object for tags is a GstTagList - . An element that is reading tags from a stream should - create an empty taglist and fill this with individual tags. Empty tag - lists can be created with gst_tag_list_new (). Then, - the element can fill the list using gst_tag_list_add () - or gst_tag_list_add_values (). - Note that elements often read metadata as strings, but the - values in the taglist might not necessarily be strings - they need to be - of the type the tag was registered as (the API documentation for each - predefined tag should contain the type). Be sure to use functions like - gst_value_transform () - to make sure that your data is of the right type. - After data reading, you can send the tags downstream with the TAG event. - When the TAG event reaches the sink, it will post the TAG message on - the pipeline's GstBus for the application to pick up. - - - We currently require the core to know the GType of tags before they are - being used, so all tags must be registered first. You can add new tags - to the list of known tags using gst_tag_register (). - If you think the tag will be useful in more cases than just your own - element, it might be a good idea to add it to gsttag.c - instead. That's up to you to decide. If you want to do it in your own - element, it's easiest to register the tag in one of your class init - functions, preferably _class_init (). - - - - - - - - Writing Tags to Streams - - Tag writers are the opposite of tag readers. Tag writers only take - metadata tags into account, since that's the only type of tags that have - to be written into a stream. Tag writers can receive tags in three ways: - internal, application and pipeline. Internal tags are tags read by the - element itself, which means that the tag writer is - in that case - a tag - reader, too. Application tags are tags provided to the element via the - TagSetter interface (which is just a layer). Pipeline tags are tags - provided to the element from within the pipeline. The element receives - such tags via the GST_EVENT_TAG event, which means - that tags writers should implement an event handler. The tag writer is - responsible for combining all these three into one list and writing them - to the output stream. - - - The example below will receive tags from both application and pipeline, - combine them and write them to the output stream. It implements the tag - setter so applications can set tags, and retrieves pipeline tags from - incoming events. - - - Warning, this example is outdated and doesn't work with the 1.0 version - of &GStreamer; anymore. - - -srcpad, buf); - } - - g_value_unset (&to); -} - -static void -gst_my_filter_task_func (GstElement *element) -{ - GstMyFilter *filter = GST_MY_FILTER (element); - GstTagSetter *tagsetter = GST_TAG_SETTER (element); - GstData *data; - GstEvent *event; - gboolean eos = FALSE; - GstTagList *taglist = gst_tag_list_new (); - - while (!eos) { - data = gst_pad_pull (filter->sinkpad); - - /* We're not very much interested in data right now */ - if (GST_IS_BUFFER (data)) - gst_buffer_unref (GST_BUFFER (data)); - event = GST_EVENT (data); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_TAG: - gst_tag_list_insert (taglist, gst_event_tag_get_list (event), - GST_TAG_MERGE_PREPEND); - gst_event_unref (event); - break; - case GST_EVENT_EOS: - eos = TRUE; - gst_event_unref (event); - break; - default: - gst_pad_event_default (filter->sinkpad, event); - break; - } - } - - /* merge tags with the ones retrieved from the application */ - if ((gst_tag_setter_get_tag_list (tagsetter)) { - gst_tag_list_insert (taglist, - gst_tag_setter_get_tag_list (tagsetter), - gst_tag_setter_get_tag_merge_mode (tagsetter)); - } - - /* write tags */ - gst_tag_list_foreach (taglist, gst_my_filter_write_tag, filter); - - /* signal EOS */ - gst_pad_push (filter->srcpad, gst_event_new (GST_EVENT_EOS)); -} -]]> - - - Note that normally, elements would not read the full stream before - processing tags. Rather, they would read from each sinkpad until they've - received data (since tags usually come in before the first data buffer) - and process that. - - - diff --git a/docs/pwg/advanced-types.xml b/docs/pwg/advanced-types.xml deleted file mode 100644 index bb1d149ce3..0000000000 --- a/docs/pwg/advanced-types.xml +++ /dev/null @@ -1,1431 +0,0 @@ - - - - Types and Properties - - There is a very large set of possible types that may be used to pass data - between elements. Indeed, each new element that is defined may use a new - data format (though unless at least one other element recognises that - format, it will be most likely be useless since nothing will be able to - link with it). - - - In order for types to be useful, and for systems like autopluggers to - work, it is necessary that all elements agree on the type definitions, - and which properties are required for each type. The &GStreamer; framework - itself simply provides the ability to define types and parameters, but - does not fix the meaning of types and parameters, and does not enforce - standards on the creation of new types. This is a matter for a policy to - decide, not technical systems to enforce. - - - For now, the policy is simple: - - - - Do not create a new type if you could use one which already exists. - - - - - If creating a new type, discuss it first with the other &GStreamer; - developers, on at least one of: IRC, mailing lists. - - - - - Try to ensure that the name for a new format is as unlikely to - conflict with anything else created already, and is not a more - generalised name than it should be. For example: "audio/compressed" - would be too generalised a name to represent audio data compressed - with an mp3 codec. Instead "audio/mp3" might be an appropriate name, - or "audio/compressed" could exist and have a property indicating the - type of compression used. - - - - - Ensure that, when you do create a new type, you specify it clearly, - and get it added to the list of known types so that other developers - can use the type correctly when writing their elements. - - - - - - - - - Building a Simple Format for Testing - - If you need a new format that has not yet been defined in our , you will want to have some general - guidelines on media type naming, properties and such. A media type would - ideally be equivalent to the Mime-type defined by IANA; else, it should - be in the form type/x-name, where type is the sort of data this media type - handles (audio, video, ...) and name should be something specific for - this specific type. Audio and video media types should try to support the - general audio/video properties (see the list), and can use their own - properties, too. To get an idea of what properties we think are useful, - see (again) the list. - - - Take your time to find the right set of properties for your type. There - is no reason to hurry. Also, experimenting with this is generally a good - idea. Experience learns that theoretically thought-out types are good, - but they still need practical use to assure that they serve their needs. - Make sure that your property names do not clash with similar properties - used in other types. If they match, make sure they mean the same thing; - properties with different types but the same names are - not allowed. - - - - - - - Typefind Functions and Autoplugging - - With only defining the types, we're not yet there. - In order for a random data file to be recognized and played back as - such, we need a way of recognizing their type out of the blue. For this - purpose, typefinding was introduced. Typefinding is the - process of detecting the type of a data stream. Typefinding consists of - two separate parts: first, there's an unlimited number of functions - that we call typefind functions, which are each - able to recognize one or more types from an input stream. Then, - secondly, there's a small engine which registers and calls each of - those functions. This is the typefind core. On top of this typefind - core, you would normally write an autoplugger, which is able to use - this type detection system to dynamically build a pipeline around an - input stream. Here, we will focus only on typefind functions. - - - A typefind function usually lives in - gst-plugins-base/gst/typefind/gsttypefindfunctions.c, - unless there's a good reason (like library dependencies) to put it - elsewhere. The reason for this centralization is to reduce the - number of plugins that need to be loaded in order to detect a stream's - type. Below is an example that will recognize AVI files, which start - with a RIFF tag, then the size of the file and then an - AVI tag: - - -static void -gst_my_typefind_function (GstTypeFind *tf, - gpointer data) -{ - guint8 *data = gst_type_find_peek (tf, 0, 12); - - if (data && - GUINT32_FROM_LE (&((guint32 *) data)[0]) == GST_MAKE_FOURCC ('R','I','F','F') && - GUINT32_FROM_LE (&((guint32 *) data)[2]) == GST_MAKE_FOURCC ('A','V','I',' ')) { - gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, - gst_caps_new_simple ("video/x-msvideo", NULL)); - } -} - -static gboolean -plugin_init (GstPlugin *plugin) -{ - if (!gst_type_find_register (plugin, "", GST_RANK_PRIMARY, - gst_my_typefind_function, "avi", - gst_caps_new_simple ("video/x-msvideo", - NULL), NULL)) - return FALSE; -} - - - Note that - gst-plugins/gst/typefind/gsttypefindfunctions.c - has some simplification macros to decrease the amount of code. Make - good use of those if you want to submit typefinding patches with new - typefind functions. - - - Autoplugging has been discussed in great detail in the Application - Development Manual. - - - - - - - List of Defined Types - - Below is a list of all the defined types in &GStreamer;. They are split - up in separate tables for audio, video, container, subtitle and other - types, for the sake of readability. Below each table might follow a - list of notes that apply to that table. In the definition of each type, - we try to follow the types and rules as defined by - IANA for as far as possible. - - - Jump directly to a specific table: - - - - - - - - - - - - - - - - - - - - Note that many of the properties are not required, - but rather optional properties. This means that - most of these properties can be extracted from the container header, - but that - in case the container header does not provide these - they - can also be extracted by parsing the stream header or the stream - content. The policy is that your element should provide the data that - it knows about by only parsing its own content, not another element's - content. Example: the AVI header provides samplerate of the contained - audio stream in the header. MPEG system streams don't. This means that - an AVI stream demuxer would provide samplerate as a property for MPEG - audio streams, whereas an MPEG demuxer would not. A decoder needing - this data would require a stream parser in between two extract this - from the header or calculate it from the stream. - - - - Table of Audio Types - - - - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - - All audio types. - - - - - - - audio/* - - All audio types - - rate - integer - greater than 0 - - The sample rate of the data, in samples (per channel) per second. - - - - channels - integer - greater than 0 - - The number of channels of audio data. - - - - channel-mask - bitmask - - - Channel positions present. See GstAudioChannelPosition. - 0 means unpositioned. - - - - format - string - - 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 - - - The format of the sample data. - - - - layout - string - "interleaved" or "non-interleaved" - - Layout of channels within a buffer. - - - - - - - - All raw audio types. - - - - - - - audio/x-raw - - Unstructured and uncompressed raw audio data. - - - - - - All properties (except channel-mask, in the mono and stereo cases) are mandatory. - - - - - - - - All encoded audio types. - - - - - - - audio/x-ac3 - AC-3 or A52 audio streams. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-adpcm - ADPCM Audio streams. - layout - string - - quicktime, dvi, - microsoft or 4xm. - - - The layout defines the packing of the samples in the stream. In - ADPCM, most formats store multiple samples per channel together. - This number of samples differs per format, hence the different - layouts. On the long term, we probably want this variable to die - and use something more descriptive, but this will do for now. - - - - block_align - integer - - Any - - - Chunk buffer size. - - - - - - - audio/x-cinepak - Audio as provided in a Cinepak (Quicktime) stream. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-dv - Audio as provided in a Digital Video stream. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-flac - Free Lossless Audio codec (FLAC). - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-gsm - Data encoded by the GSM codec. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-alaw - A-Law Audio. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-mulaw - Mu-Law Audio. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-mace - MACE Audio (used in Quicktime). - maceversion - integer - 3 or 6 - - The version of the MACE audio codec used to encode the stream. - - - - - - - audio/mpeg - - Audio data compressed using the MPEG audio encoding scheme. - - mpegversion - integer - 1, 2 or 4 - - The MPEG-version used for encoding the data. The value 1 refers - to MPEG-1, -2 and -2.5 layer 1, 2 or 3. The values 2 and 4 refer - to the MPEG-AAC audio encoding schemes. - - - - framed - boolean - 0 or 1 - - A true value indicates that each buffer contains exactly one - frame. A false value indicates that frames and buffers do not - necessarily match up. - - - - layer - integer - 1, 2, or 3 - - The compression scheme layer used to compress the data - (only if mpegversion=1). - - - - bitrate - integer - greater than 0 - - The bitrate, in bits per second. For VBR (variable bitrate) - MPEG data, this is the average bitrate. - - - - - - - audio/x-qdm2 - Data encoded by the QDM version 2 codec. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-pn-realaudio - Realmedia Audio data. - raversion - integer - 1 or 2 - - The version of the Real Audio codec used to encode the stream. - 1 stands for a 14k4 stream, 2 stands for a 28k8 stream. - - - - - - - audio/x-speex - Data encoded by the Speex audio codec - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-vorbis - Vorbis audio data - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-wma - Windows Media Audio - wmaversion - integer - 1,2 or 3 - - The version of the WMA codec used to encode the stream. - - - - - - - audio/x-paris - Ensoniq PARIS audio - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-svx - Amiga IFF / SVX8 / SV16 audio - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-nist - Sphere NIST audio - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-voc - Sound Blaster VOC audio - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-ircam - Berkeley/IRCAM/CARL audio - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-w64 - Sonic Foundry's 64 bit RIFF/WAV - - - - - There are currently no specific properties defined or needed for - this type. - - - - - -
- - - Table of Video Types - - - - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - - All video types. - - - - - - - video/* - - All video types - - width - integer - greater than 0 - The width of the video image - - - height - integer - greater than 0 - The height of the video image - - - framerate - fraction - greater or equal 0; default 0/1 - - The (average) framerate in frames per second. Note that this - property does not guarantee in any way that - it will actually come close to this value. If you need a fixed - framerate, please use an element that provides that (such as - videorate). 0/1 means a variable framerate. - - - - max-framerate - fraction - greater or equal 0; default as framerate - - For variable framerates, the maximum framerate that is expected. - Only valid when framerate is 0/1. - - - - views - integer - greater than 0; default 1 - - The number of views for multiview video. Each buffer contains - multiple GstVideoMeta buffers that describe each view. Use the - frame ID to get access to the different views. - - - - interlace-mode - string - progressive, interleaved, mixed, fields; default progressive - - The interlace mode. Extra buffer flags describe the frame and fields. - - - - chroma-site - string - jpeg, mpeg2, dv; default UNKNOWN - - The chroma siting of the video frames. - - - - colorimetry - string - bt601, bt709, smpte240m; default UNKNOWN - - The colorimetry of the video frames. - - - - pixel-aspect-ratio - fraction - greater than 0; default 1/1 - - The pixel aspect ratio of the video. - - - - format - string - - I420 YV12 YUY2 UYVY AYUV RGBx BGRx xRGB xBGR RGBA BGRA ARGB ABGR RGB BGR Y41B Y42B - YVYU Y444 v210 v216 NV12 NV21 GRAY8 GRAY16_BE GRAY16_LE - v308 RGB16 BGR16 RGB15 BGR15 UYVP A420 RGB8P YUV9 YVU9 - IYU1 ARGB64 AYUV64 r210 I420_10LE I420_10BE I422_10LE I422_10BE - - - The format of the video. See FourCC definition site - for references and definitions. YUY2, YVYU and UYVY are 4:2:2 - packed-pixel, Y41P is 4:1:1 packed-pixel and IYU2 is 4:4:4 - packed-pixel. Y42B is 4:2:2 planar, YV12 and I420 are 4:2:0 - planar, Y41B is 4:1:1 planar and YUV9 and YVU9 are 4:1:0 planar. - Y800 contains Y-samples only (black/white). - - - - - - - - All raw video types. - - - - - - - video/x-raw - Unstructured and uncompressed raw video data. - - - - - The properties width, height and format are mandatory. - - - - - - - - All encoded video types. - - - - - - - video/x-3ivx - 3ivx video. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-divx - DivX video. - divxversion - integer - 3, 4 or 5 - - Version of the DivX codec used to encode the stream. - - - - - - - video/x-dv - Digital Video. - systemstream - boolean - FALSE - - Indicates that this stream is not a system - container stream. - - - - - - - video/x-ffv - FFMpeg video. - ffvversion - integer - 1 - - Version of the FFMpeg video codec used to encode the stream. - - - - - - - video/x-h263 - H-263 video. - variant - string - itu, lead, microsoft, vdolive, vivo, xirlink - - Vendor specific variant of the format. 'itu' is the standard. - - - - h263version - string - h263, h263p, h263pp - - Enhanced versions of the h263 codec. - - - - - - - video/x-h264 - H-264 video. - variant - string - itu, videosoft - - Vendor specific variant of the format. 'itu' is the standard. - - - - - - - video/x-huffyuv - Huffyuv video. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-indeo - Indeo video. - indeoversion - integer - 3 - - Version of the Indeo codec used to encode this stream. - - - - - - - video/x-intel-h263 - H-263 video. - variant - string - intel - - Vendor specific variant of the format. - - - - - - - video/x-jpeg - Motion-JPEG video. - - - - - There are currently no specific properties defined or needed for - this type. Note that video/x-jpeg only applies to Motion-JPEG - pictures (YUY2 colourspace). RGB colourspace JPEG images are - referred to as image/jpeg (JPEG image). - - - - - - - video/mpeg - MPEG video. - mpegversion - integer - 1, 2 or 4 - - Version of the MPEG codec that this stream was encoded with. - Note that we have different media types for 3ivx, XviD, DivX and - "standard" ISO MPEG-4. This is not a good - thing and we're fully aware of this. However, we do not have a - solution yet. - - - - systemstream - boolean - FALSE - - Indicates that this stream is not a system - container stream. - - - - - - - video/x-msmpeg - Microsoft MPEG-4 video deviations. - msmpegversion - integer - 41, 42 or 43 - - Version of the MS-MPEG-4-like codec that was used to encode this - version. A value of 41 refers to MS MPEG 4.1, 42 to 4.2 and 43 - to version 4.3. - - - - - - - video/x-msvideocodec - Microsoft Video 1 (oldish codec). - msvideoversion - integer - 1 - - Version of the codec - always 1. - - - - - - - video/x-pn-realvideo - Realmedia video. - rmversion - integer - 1, 2 or 3 - - Version of the Real Video codec that this stream was encoded - with. - - - - - - - video/x-rle - RLE animation format. - layout - string - "microsoft" or "quicktime" - - The RLE format inside the Microsoft AVI container has a - different byte layout than the RLE format inside Apple's - Quicktime container; this property keeps track of the - layout. - - - - depth - integer - 1 to 64 - - Bit depth of the used palette. This means that the palette - that belongs to this format defines 2^depth colors. - - - - palette_data - GstBuffer - - - Buffer containing a color palette (in native-endian RGBA) used - by this format. The buffer is of size 4*2^depth. - - - - - - - video/x-svq - Sorensen Video. - svqversion - integer - 1 or 3 - - Version of the Sorensen codec that the stream was encoded with. - - - - - - - video/x-tarkin - Tarkin video. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-theora - Theora video. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-vp3 - VP-3 video. - - - - - There are currently no specific properties defined or needed for - this type. Note that we have different media types for VP-3 and - Theora, which is not necessarily a good idea. This could probably - be improved. - - - - - - - video/x-wmv - Windows Media Video - wmvversion - integer - 1,2 or 3 - - Version of the WMV codec that the stream was encoded with. - - - - - - - video/x-xvid - XviD video. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - - All image types. - - - - - - - image/gif - Graphics Interchange Format. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - image/jpeg - Joint Picture Expert Group Image. - - - - - There are currently no specific properties defined or needed for - this type. Note that image/jpeg only applies to RGB-colourspace - JPEG images; YUY2-colourspace JPEG pictures are referred to as - video/x-jpeg ("Motion JPEG"). - - - - - - - image/png - Portable Network Graphics Image. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - image/tiff - Tagged Image File Format. - - - - - There are currently no specific properties defined or needed for - this type. - - - - -
- - - Table of Container Types - - - - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - video/x-ms-asf - Advanced Streaming Format (ASF). - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-msvideo - AVI. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/x-dv - Digital Video. - systemstream - boolean - TRUE - - Indicates that this is a container system stream rather than an - elementary video stream. - - - - - - - video/x-matroska - Matroska. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/mpeg - Motion Pictures Expert Group System Stream. - systemstream - boolean - TRUE - - Indicates that this is a container system stream rather than an - elementary video stream. - - - - - - - application/ogg - Ogg. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - video/quicktime - Quicktime. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - application/vnd.rn-realmedia - RealMedia. - - - - - There are currently no specific properties defined or needed for - this type. - - - - - - - audio/x-wav - WAV. - - - - - There are currently no specific properties defined or needed for - this type. - - - - -
- - - Table of Subtitle Types - - - - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - - - - - - - None defined yet. - - - - -
- - - Table of Other Types - - - - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - - - - - - - None defined yet. - - - - -
-
-
diff --git a/docs/pwg/appendix-checklist.xml b/docs/pwg/appendix-checklist.xml deleted file mode 100644 index bd118c4038..0000000000 --- a/docs/pwg/appendix-checklist.xml +++ /dev/null @@ -1,195 +0,0 @@ - - Things to check when writing an element - - This chapter contains a fairly random selection of things to take care - of when writing an element. It's up to you how far you're going to stick - to those guidelines. However, keep in mind that when you're writing an - element and hope for it to be included in the mainstream &GStreamer; - distribution, it has to meet those requirements. - As far as possible, we will try to explain why those requirements are - set. - - - - About states - - - - - Make sure the state of an element gets reset when going to - NULL. Ideally, this should set all - object properties to their original state. This function - should also be called from _init. - - - - - Make sure an element forgets everything - about its contained stream when going from - PAUSED to READY. In - READY, all stream states are reset. An - element that goes from PAUSED to - READY and back to - PAUSED should start reading the - stream from the start again. - - - - - People that use gst-launch for testing have - the tendency to not care about cleaning up. This is - wrong. An element should be tested using - various applications, where testing not only means to make - sure it doesn't crash, but also to test for memory leaks - using tools such as valgrind. Elements have to - be reusable in a pipeline after having been reset. - - - - - - - Debugging - - - - - Elements should never use their standard - output for debugging (using functions such as printf - () or g_print ()). Instead, - elements should use the logging functions provided by &GStreamer;, - named GST_DEBUG (), - GST_LOG (), GST_INFO (), - GST_WARNING () and - GST_ERROR (). The various logging levels can - be turned on and off at runtime and can thus be used for solving - issues as they turn up. Instead of GST_LOG () - (as an example), you can also use GST_LOG_OBJECT - () to print the object that you're logging output for. - - - - - Ideally, elements should use their own debugging category. Most - elements use the following code to do that: - - -GST_DEBUG_CATEGORY_STATIC (myelement_debug); -#define GST_CAT_DEFAULT myelement_debug - -[..] - -static void -gst_myelement_class_init (GstMyelementClass *klass) -{ -[..] - GST_DEBUG_CATEGORY_INIT (myelement_debug, "myelement", - 0, "My own element"); -} - - - At runtime, you can turn on debugging using the commandline - option --gst-debug=myelement:5. - - - - - Elements should use GST_DEBUG_FUNCPTR when setting pad functions or - overriding element class methods, for example: - -gst_pad_set_event_func (myelement->srcpad, - GST_DEBUG_FUNCPTR (my_element_src_event)); - - This makes debug output much easier to read later on. - - - - - Elements that are aimed for inclusion into one of the GStreamer - modules should ensure consistent naming of the element name, - structures and function names. For example, if the element type is - GstYellowFooDec, functions should be prefixed with - gst_yellow_foo_dec_ and the element should be registered - as 'yellowfoodec'. Separate words should be separate in this scheme, - so it should be GstFooDec and gst_foo_dec, and not GstFoodec and - gst_foodec. - - - - - - - Querying, events and the like - - - - - All elements to which it applies (sources, sinks, demuxers) - should implement query functions on their pads, so that - applications and neighbour elements can request the current - position, the stream length (if known) and so on. - - - - - Elements should make sure they forward events they do not - handle with gst_pad_event_default (pad, parent, event) instead of - just dropping them. Events should never be dropped unless - specifically intended. - - - - - Elements should make sure they forward queries they do not - handle with gst_pad_query_default (pad, parent, query) instead of - just dropping them. - - - - - - - Testing your element - - - - - gst-launch is not a good - tool to show that your element is finished. Applications such as - Rhythmbox and Totem (for GNOME) or AmaroK (for KDE) - are. gst-launch will not - test various things such as proper clean-up on reset, event - handling, querying and so on. - - - - - Parsers and demuxers should make sure to check their input. Input - cannot be trusted. Prevent possible buffer overflows and the like. - Feel free to error out on unrecoverable stream errors. Test your - demuxer using stream corruption elements such as - breakmydata (included in gst-plugins). It - will randomly insert, delete and modify bytes in a stream, and is - therefore a good test for robustness. If your element crashes - when adding this element, your element needs fixing. If it errors - out properly, it's good enough. Ideally, it'd just continue to - work and forward data as much as possible. - - - - - Demuxers should not assume that seeking works. Be prepared to - work with unseekable input streams (e.g. network sources) as - well. - - - - - Sources and sinks should be prepared to be assigned another clock - then the one they expose themselves. Always use the provided clock - for synchronization, else you'll get A/V sync issues. - - - - - diff --git a/docs/pwg/appendix-licensing.xml b/docs/pwg/appendix-licensing.xml deleted file mode 100644 index ab1d192c57..0000000000 --- a/docs/pwg/appendix-licensing.xml +++ /dev/null @@ -1,38 +0,0 @@ - - GStreamer licensing - - How to license the code you write for <application>GStreamer</application> - -GStreamer is a plugin-based framework licensed under the LGPL. The reason -for this choice in licensing is to ensure that everyone can use GStreamer -to build applications using licenses of their choice. - - -To keep this policy viable, the GStreamer community has made a few -licensing rules for code to be included in GStreamer's core or GStreamer's -official modules, like our plugin packages. We require that all code going -into our core package is LGPL. For the plugin code, we require the use of -the LGPL for all plugins written from scratch or linking to external -libraries. The only exception to this is when plugins contain older code -under more liberal licenses (like the MPL or BSD). They can use those -licenses instead and will still be considered for inclusion. We do not -accept GPL code to be added to our plugins module, but we do accept -LGPL-licensed plugins using an external GPL library. The reason for -demanding plugins be licensed under the LGPL, even when using a GPL -library, is that other developers might want to use the plugin code as a -template for plugins linking to non-GPL libraries. - - -We also plan on splitting out the plugins using GPL libraries into a -separate package eventually and implement a system which makes sure an -application will not be able to access these plugins unless it uses some -special code to do so. The point of this is not to block GPL-licensed -plugins from being used and developed, but to make sure people are not -unintentionally violating the GPL license of said plugins. - - -This advisory is part of a bigger advisory with a FAQ which you can find -on the GStreamer website - - - diff --git a/docs/pwg/appendix-porting.xml b/docs/pwg/appendix-porting.xml deleted file mode 100644 index ab457a8ce7..0000000000 --- a/docs/pwg/appendix-porting.xml +++ /dev/null @@ -1,196 +0,0 @@ - - Porting 0.8 plug-ins to 0.10 - - This section of the appendix will discuss shortly what changes to - plugins will be needed to quickly and conveniently port most - applications from &GStreamer;-0.8 to &GStreamer;-0.10, with references - to the relevant sections in this Plugin Writer's Guide where needed. - With this list, it should be possible to port most plugins to - &GStreamer;-0.10 in less than a day. Exceptions are elements that will - require a base class in 0.10 (sources, sinks), in which case it may take - a lot longer, depending on the coder's skills (however, when using the - GstBaseSink and GstBaseSrc - base-classes, it shouldn't be all too bad), and elements requiring - the deprecated bytestream interface, which should take 1-2 days with - random access. The scheduling parts of muxers will also need a rewrite, - which will take about the same amount of time. - - - - List of changes - - - - Discont events have been replaced by newsegment events. In 0.10, it is - essential that you send a newsegment event downstream before you send - your first buffer (in 0.8 the scheduler would invent discont events if - you forgot them, in 0.10 this is no longer the case). - - - - - In 0.10, buffers have caps attached to them. Elements should allocate - new buffers with gst_pad_alloc_buffer (). See - for more details. - - - - - Most functions returning an object or an object property have - been changed to return its own reference rather than a constant - reference of the one owned by the object itself. The reason for - this change is primarily thread-safety. This means effectively - that return values of functions such as - gst_element_get_pad (), - gst_pad_get_name (), - gst_pad_get_parent (), - gst_object_get_parent (), - and many more like these - have to be free'ed or unreferenced after use. Check the API - references of each function to know for sure whether return - values should be free'ed or not. - - - - - In 0.8, scheduling could happen in any way. Source elements could - be _get ()-based or _loop - ()-based, and any other element could be _chain - ()-based or _loop ()-based, with - no limitations. Scheduling in 0.10 is simpler for the scheduler, - and the element is expected to do some more work. Pads get - assigned a scheduling mode, based on which they can either - operate in random access-mode, in pipeline driving mode or in - push-mode. all this is documented in detail in . As a result of this, the bytestream - object no longer exists. Elements requiring byte-level access should - now use random access on their sinkpads. - - - - - Negotiation is asynchronous. This means that downstream negotiation - is done as data comes in and upstream negotiation is done whenever - renegotiation is required. All details are described in - . - - - - - For as far as possible, elements should try to use existing base - classes in 0.10. Sink and source elements, for example, could derive - from GstBaseSrc and - GstBaseSink. Audio sinks or sources could even - derive from audio-specific base classes. All existing base classes - have been discussed in and the - next few chapters. - - - - - In 0.10, event handling and buffers are separated once again. This - means that in order to receive events, one no longer has to set the - GST_FLAG_EVENT_AWARE flag, but can simply - set an event handling function on the element's sinkpad(s), using - the function gst_pad_set_event_function (). The - _chain ()-function will only receive buffers. - - - - - Although core will wrap most threading-related locking for you (e.g. - it takes the stream lock before calling your data handling - functions), you are still responsible for locking around certain - functions, e.g. object properties. Be sure to lock properly here, - since applications will change those properties in a different thread - than the thread which does the actual data passing! You can use the - GST_OBJECT_LOCK () and GST_OBJECT_UNLOCK - () helpers in most cases, fortunately, which grabs the - default property lock of the element. - - - - - GstValueFixedList and all - *_fixed_list_* () functions were renamed to - GstValueArray and *_array_* - (). - - - - - The semantics of GST_STATE_PAUSED and - GST_STATE_PLAYING have changed for elements that - are not sink elements. Non-sink elements need to be able to accept - and process data already in the GST_STATE_PAUSED - state now (i.e. when prerolling the pipeline). More details can be - found in . - - - - - If your plugin's state change function hasn't been superseded by - virtual start() and stop() methods of one of the new base classes, - then your plugin's state change functions may need to be changed in - order to safely handle concurrent access by multiple threads. Your - typical state change function will now first handle upwards state - changes, then chain up to the state change function of the parent - class (usually GstElementClass in these cases), and only then handle - downwards state changes. See the vorbis decoder plugin in - gst-plugins-base for an example. - - - The reason for this is that in the case of downwards state changes - you don't want to destroy allocated resources while your plugin's - chain function (for example) is still accessing those resources in - another thread. Whether your chain function might be running or not - depends on the state of your plugin's pads, and the state of those - pads is closely linked to the state of the element. Pad states are - handled in the GstElement class's state change function, including - proper locking, that's why it is essential to chain up before - destroying allocated resources. - - - As already mentioned above, you should really rewrite your plugin - to derive from one of the new base classes though, so you don't have - to worry about these things, as the base class will handle it for you. - There are no base classes for decoders and encoders yet, so the above - paragraphs about state changes definitively apply if your plugin is a - decoder or an encoder. - - - - - gst_pad_set_link_function (), which used to set - a function that would be called when a format was negotiated between - two GstPads, now sets a function that is - called when two elements are linked together in an application. For - all practical purposes, you most likely want to use the function - gst_pad_set_setcaps_function (), nowadays, which - sets a function that is called when the format streaming over a pad - changes (so similar to _set_link_function () in - &GStreamer;-0.8). - - - If the element is derived from a GstBase class, - then override the set_caps (). - - - - - gst_pad_use_explicit_caps () has been replaced by - gst_pad_use_fixed_caps (). You can then set the - fixed caps to use on a pad with gst_pad_set_caps (). - - - - - - - - Porting 0.10 plug-ins to 1.0 - - You can find the list of changes in the - Porting to 1.0 document. - - diff --git a/docs/pwg/appendix-python.xml b/docs/pwg/appendix-python.xml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/pwg/base.css b/docs/pwg/base.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/pwg/building-boiler.xml b/docs/pwg/building-boiler.xml deleted file mode 100644 index 251bf33173..0000000000 --- a/docs/pwg/building-boiler.xml +++ /dev/null @@ -1,466 +0,0 @@ - - - - Constructing the Boilerplate - - In this chapter you will learn how to construct the bare minimum code for a - new plugin. Starting from ground zero, you will see how to get the - &GStreamer; template source. Then you will learn how to use a few basic - tools to copy and modify a template plugin to create a new plugin. If you - follow the examples here, then by the end of this chapter you will have a - functional audio filter plugin that you can compile and use in &GStreamer; - applications. - - - - - - Getting the GStreamer Plugin Templates - - There are currently two ways to develop a new plugin for &GStreamer;: You - can write the entire plugin by hand, or you can copy an existing plugin - template and write the plugin code you need. The second method is by far - the simpler of the two, so the first method will not even be described - here. (Errm, that is, it is left as an exercise to the - reader.) - - - The first step is to check out a copy of the - gst-template git module to get an important tool and - the source code template for a basic &GStreamer; plugin. To check out the - gst-template module, make sure you are connected to - the internet, and type the following commands at a command console: - - -shell $ git clone git://anongit.freedesktop.org/gstreamer/gst-template.git -Initialized empty Git repository in /some/path/gst-template/.git/ -remote: Counting objects: 373, done. -remote: Compressing objects: 100% (114/114), done. -remote: Total 373 (delta 240), reused 373 (delta 240) -Receiving objects: 100% (373/373), 75.16 KiB | 78 KiB/s, done. -Resolving deltas: 100% (240/240), done. - - - This command will check out a series of files and directories into - gst-template. The template you - will be using is in the - gst-template/gst-plugin/ - directory. You should look over the files in that directory to get a - general idea of the structure of a source tree for a plugin. - - - If for some reason you can't access the git repository, you can also - - download a snapshot of the latest revision via the cgit web - interface. - - - - - - - Using the Project Stamp - - The first thing to do when making a new element is to specify some basic - details about it: what its name is, who wrote it, what version number it - is, etc. We also need to define an object to represent the element and to - store the data the element needs. These details are collectively known as - the boilerplate. - - - The standard way of defining the boilerplate is simply to write some code, - and fill in some structures. As mentioned in the previous section, the - easiest way to do this is to copy a template and add functionality - according to your needs. To help you do so, there is a tool in the - ./gst-plugin/tools/ directory. - This tool, make_element, is a command line utility - that creates the boilerplate code for you. - - - To use make_element, first open up a terminal window. - Change to the gst-template/gst-plugin/src - directory, and then run the make_element command. The - arguments to the make_element are: - - - - the name of the plugin, and - - - - the source file that the tool will use. By default, - gstplugin is used. - - - - - For example, the following commands create the MyFilter plugin based on - the plugin template and put the output files in the - gst-template/gst-plugin/src - directory: - - -shell $ cd gst-template/gst-plugin/src -shell $ ../tools/make_element MyFilter - - - - Capitalization is important for the name of the plugin. Keep in mind - that under some operating systems, capitalization is also important - when specifying directory and file names in general. - - - - The last command creates two files: - gstmyfilter.c and - gstmyfilter.h. - - - - It is recommended that you create a copy of the gst-plugin - directory before continuing. - - - - Now one needs to adjust the Makefile.am to use the - new filenames and run autogen.sh from the parent - directory to bootstrap the build environment. After that, the project - can be built and installed using the well known - make && sudo make install commands. - - - - Be aware that by default autogen.sh and - configure would choose /usr/local - as a default location. One would need to add - /usr/local/lib/gstreamer-1.0 - to GST_PLUGIN_PATH in order to make the new plugin - show up in a gstreamer that's been installed from packages. - - - - - FIXME: this section is slightly outdated. gst-template is still useful - as an example for a minimal plugin build system skeleton. However, for - creating elements the tool gst-element-maker from gst-plugins-bad is - recommended these days. - - - - - - - - Examining the Basic Code - - First we will examine the code you would be likely to place in a header - file (although since the interface to the code is entirely defined by the - plugin system, and doesn't depend on reading a header file, this is not - crucial.) - - - - Example Plugin Header File - -#include <gst/gst.h> - -/* Definition of structure storing data for this element. */ -typedef struct _GstMyFilter { - GstElement element; - - GstPad *sinkpad, *srcpad; - - gboolean silent; - - - -} GstMyFilter; - -/* Standard definition defining a class for this element. */ -typedef struct _GstMyFilterClass { - GstElementClass parent_class; -} GstMyFilterClass; - -/* Standard macros for defining types for this element. */ -#define GST_TYPE_MY_FILTER (gst_my_filter_get_type()) -#define GST_MY_FILTER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter)) -#define GST_MY_FILTER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass)) -#define GST_IS_MY_FILTER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER)) -#define GST_IS_MY_FILTER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER)) - -/* Standard function returning type information. */ -GType gst_my_filter_get_type (void); - - - - Using this header file, you can use the following macro to setup - the GObject basics in your source file so - that all functions will be called appropriately: - - -#include "filter.h" - -G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); - - - - - - - Element metadata - - The Element metadata provides extra element information. It is configured - with gst_element_class_set_metadata or - gst_element_class_set_static_metadata which takes the - following parameters: - - - - A long, English, name for the element. - - The type of the element, see the docs/design/draft-klass.txt document - in the GStreamer core source tree for details and examples. - - A brief description of the purpose of the element. - - The name of the author of the element, optionally followed by a contact - email address in angle brackets. - - - - For example: - - -gst_element_class_set_static_metadata (klass, - "An example plugin", - "Example/FirstExample", - "Shows the basic structure of a plugin", - "your name <your.name@your.isp>"); - - - The element details are registered with the plugin during - the _class_init () function, which is part of - the GObject system. The _class_init () function - should be set for this GObject in the function where you register - the type with GLib. - - -static void -gst_my_filter_class_init (GstMyFilterClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - -[..] - gst_element_class_set_static_metadata (element_klass, - "An example plugin", - "Example/FirstExample", - "Shows the basic structure of a plugin", - "your name <your.name@your.isp>"); - -} - - - - - - - GstStaticPadTemplate - - A GstStaticPadTemplate is a description of a pad that the element will - (or might) create and use. It contains: - - - - A short name for the pad. - - - Pad direction. - - - - Existence property. This indicates whether the pad exists always (an - always pad), only in some cases (a - sometimes pad) or only if the application requested - such a pad (a request pad). - - - - Supported types by this element (capabilities). - - - - For example: - - -static GstStaticPadTemplate sink_factory = -GST_STATIC_PAD_TEMPLATE ( - "sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("ANY") -); - - - - - Those pad templates are registered during the - _class_init () function with the - gst_element_class_add_pad_template (). For this - function you need a handle the GstPadTemplate - which you can create from the static pad template with - gst_static_pad_template_get (). See below for more - details on this. - - - Pads are created from these static templates in the element's - _init () function using - gst_pad_new_from_static_template (). - In order to create a new pad from this - template using gst_pad_new_from_static_template (), you - will need to declare the pad template as a global variable. More on - this subject in . - - -static GstStaticPadTemplate sink_factory = [..], - src_factory = [..]; - -static void -gst_my_filter_class_init (GstMyFilterClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -[..] - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - - - - The last argument in a template is its type - or list of supported types. In this example, we use 'ANY', which means - that this element will accept all input. In real-life situations, you - would set a media type and optionally a set of properties to make sure - that only supported input will come in. This representation should be - a string that starts with a media type, then a set of comma-separates - properties with their supported values. In case of an audio filter that - supports raw integer 16-bit audio, mono or stereo at any samplerate, the - correct template would look like this: - - - - - - Values surrounded by curly brackets ({ and - }) are lists, values surrounded by square brackets - ([ and ]) are ranges. - Multiple sets of types are supported too, and should be separated by - a semicolon (;). Later, in the chapter on pads, we will - see how to use types to know the exact format of a stream: - . - - - - - - - Constructor Functions - - Each element has two functions which are used for construction of an - element. The _class_init() function, - which is used to initialise the class only once (specifying what signals, - arguments and virtual functions the class has and setting up global - state); and the _init() function, which is used to - initialise a specific instance of this type. - - - - - - - The plugin_init function - - Once we have written code defining all the parts of the plugin, we need to - write the plugin_init() function. This is a special function, which is - called as soon as the plugin is loaded, and should return TRUE or FALSE - depending on whether it loaded initialized any dependencies correctly. - Also, in this function, any supported element type in the plugin should - be registered. - - - - - - - - Note that the information returned by the plugin_init() function will be - cached in a central registry. For this reason, it is important that the - same information is always returned by the function: for example, it - must not make element factories available based on runtime conditions. - If an element can only work in certain conditions (for example, if the - soundcard is not being used by some other process) this must be reflected - by the element being unable to enter the READY state if unavailable, - rather than the plugin attempting to deny existence of the plugin. - - - diff --git a/docs/pwg/building-chainfn.xml b/docs/pwg/building-chainfn.xml deleted file mode 100644 index 137ca49632..0000000000 --- a/docs/pwg/building-chainfn.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - The chain function - - The chain function is the function in which all data processing takes - place. In the case of a simple filter, _chain () - functions are mostly linear functions - so for each incoming buffer, - one buffer will go out, too. Below is a very simple implementation of - a chain function: - - - -static GstFlowReturn gst_my_filter_chain (GstPad *pad, - GstObject *parent, - GstBuffer *buf); - -[..] - -static void -gst_my_filter_init (GstMyFilter * filter) -{ -[..] - /* configure chain function on the pad before adding - * the pad to the element */ - gst_pad_set_chain_function (filter->sinkpad, - gst_my_filter_chain); -[..] -} - -static GstFlowReturn -gst_my_filter_chain (GstPad *pad, - GstObject *parent, - GstBuffer *buf) -{ - GstMyFilter *filter = GST_MY_FILTER (parent); - - if (!filter->silent) - g_print ("Have data of size %" G_GSIZE_FORMAT" bytes!\n", - gst_buffer_get_size (buf)); - - return gst_pad_push (filter->srcpad, buf); -} - - - - Obviously, the above doesn't do much useful. Instead of printing that the - data is in, you would normally process the data there. Remember, however, - that buffers are not always writeable. - - - In more advanced elements (the ones that do event processing), you may want - to additionally specify an event handling function, which will be called - when stream-events are sent (such as caps, end-of-stream, newsegment, tags, etc.). - - -static void -gst_my_filter_init (GstMyFilter * filter) -{ -[..] - gst_pad_set_event_function (filter->sinkpad, - gst_my_filter_sink_event); -[..] -} - - - -static gboolean -gst_my_filter_sink_event (GstPad *pad, - GstObject *parent, - GstEvent *event) -{ - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - /* we should handle the format here */ - break; - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - break; - default: - break; - } - - return gst_pad_event_default (pad, parent, event); -} - -static GstFlowReturn -gst_my_filter_chain (GstPad *pad, - GstObject *parent, - GstBuffer *buf) -{ - GstMyFilter *filter = GST_MY_FILTER (parent); - GstBuffer *outbuf; - - outbuf = gst_my_filter_process_data (filter, buf); - gst_buffer_unref (buf); - if (!outbuf) { - /* something went wrong - signal an error */ - GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL)); - return GST_FLOW_ERROR; - } - - return gst_pad_push (filter->srcpad, outbuf); -} - - - - In some cases, it might be useful for an element to have control over the - input data rate, too. In that case, you probably want to write a so-called - loop-based element. Source elements (with only source - pads) can also be get-based elements. These concepts - will be explained in the advanced section of this guide, and in the section - that specifically discusses source pads. - - diff --git a/docs/pwg/building-eventfn.xml b/docs/pwg/building-eventfn.xml deleted file mode 100644 index b72e376bf3..0000000000 --- a/docs/pwg/building-eventfn.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - The event function - - The event function notifies you of special events that happen in - the datastream (such as caps, end-of-stream, newsegment, tags, etc.). - Events can travel both upstream and downstream, so you can receive them - on sink pads as well as source pads. - - - Below follows a very simple event function that we install on the sink - pad of our element. - - -sinkpad, - gst_my_filter_sink_event); -[..] -} - -static gboolean -gst_my_filter_sink_event (GstPad *pad, - GstObject *parent, - GstEvent *event) -{ - gboolean ret; - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - /* we should handle the format here */ - - /* push the event downstream */ - ret = gst_pad_push_event (filter->srcpad, event); - break; - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - - ret = gst_pad_event_default (pad, parent, event); - break; - default: - /* just call the default handler */ - ret = gst_pad_event_default (pad, parent, event); - break; - } - return ret; -} -]]> - - - It is a good idea to call the default event handler - gst_pad_event_default () for unknown events. - Depending on the event type, the default handler will forward - the event or simply unref it. The CAPS event is by default not - forwarded so we need to do this in the event handler ourselves. - - diff --git a/docs/pwg/building-pads.xml b/docs/pwg/building-pads.xml deleted file mode 100644 index 5e31648596..0000000000 --- a/docs/pwg/building-pads.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - Specifying the pads - - As explained before, pads are the port through which data goes in and out - of your element, and that makes them a very important item in the process - of element creation. In the boilerplate code, we have seen how static pad - templates take care of registering pad templates with the element class. - Here, we will see how to create actual elements, use an _event - ()-function to configure for a particular format and how to - register functions to let data flow through the element. - - - In the element _init () function, you create the pad - from the pad template that has been registered with the element class in - the _class_init () function. After creating the pad, - you have to set a _chain () function pointer that will - receive and process the input data on the sinkpad. - You can optionally also set an _event () function - pointer and a _query () function pointer. - Alternatively, pads can also operate in looping mode, which means that they - can pull data themselves. More on this topic later. After that, you have - to register the pad with the element. This happens like this: - - - - - -static void -gst_my_filter_init (GstMyFilter *filter) -{ - /* pad through which data comes in to the element */ - filter->sinkpad = gst_pad_new_from_static_template ( - &sink_template, "sink"); - /* pads are configured here with gst_pad_set_*_function () */ - - - - gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); - - /* pad through which data goes out of the element */ - filter->srcpad = gst_pad_new_from_static_template ( - &src_template, "src"); - /* pads are configured here with gst_pad_set_*_function () */ - - - - gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - - /* properties initial value */ - filter->silent = FALSE; -} - - - - - diff --git a/docs/pwg/building-props.xml b/docs/pwg/building-props.xml deleted file mode 100644 index 10f7d77b4c..0000000000 --- a/docs/pwg/building-props.xml +++ /dev/null @@ -1,169 +0,0 @@ - - - - Adding Properties - - The primary and most important way of controlling how an element behaves, - is through GObject properties. GObject properties are defined in the - _class_init () function. The element optionally - implements a _get_property () and a - _set_property () function. These functions will be - notified if an application changes or requests the value of a property, - and can then fill in the value or take action required for that property - to change value internally. - - - You probably also want to keep an instance variable around - with the currently configured value of the property that you use in the - get and set functions. - Note that GObject will not automatically set your - instance variable to the default value, you will have to do that in the - _init () function of your element. - - - -/* properties */ -enum { - PROP_0, - PROP_SILENT - /* FILL ME */ -}; - -static void gst_my_filter_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gst_my_filter_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void -gst_my_filter_class_init (GstMyFilterClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - /* define virtual function pointers */ - object_class->set_property = gst_my_filter_set_property; - object_class->get_property = gst_my_filter_get_property; - - /* define properties */ - g_object_class_install_property (object_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", - "Whether to be very verbose or not", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_my_filter_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GstMyFilter *filter = GST_MY_FILTER (object); - - switch (prop_id) { - case PROP_SILENT: - filter->silent = g_value_get_boolean (value); - g_print ("Silent argument was changed to %s\n", - filter->silent ? "true" : "false"); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_my_filter_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GstMyFilter *filter = GST_MY_FILTER (object); - - switch (prop_id) { - case PROP_SILENT: - g_value_set_boolean (value, filter->silent); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - - - The above is a very simple example of how properties are used. Graphical - applications will use these properties and will display a - user-controllable widget with which these properties can be changed. - This means that - for the property to be as user-friendly - as possible - you should be as exact as possible in the definition of the - property. Not only in defining ranges in between which valid properties - can be located (for integers, floats, etc.), but also in using very - descriptive (better yet: internationalized) strings in the definition of - the property, and if possible using enums and flags instead of integers. - The GObject documentation describes these in a very complete way, but - below, we'll give a short example of where this is useful. Note that using - integers here would probably completely confuse the user, because they - make no sense in this context. The example is stolen from videotestsrc. - - -typedef enum { - GST_VIDEOTESTSRC_SMPTE, - GST_VIDEOTESTSRC_SNOW, - GST_VIDEOTESTSRC_BLACK -} GstVideotestsrcPattern; - -[..] - -#define GST_TYPE_VIDEOTESTSRC_PATTERN (gst_videotestsrc_pattern_get_type ()) -static GType -gst_videotestsrc_pattern_get_type (void) -{ - static GType videotestsrc_pattern_type = 0; - - if (!videotestsrc_pattern_type) { - static GEnumValue pattern_types[] = { - { GST_VIDEOTESTSRC_SMPTE, "SMPTE 100% color bars", "smpte" }, - { GST_VIDEOTESTSRC_SNOW, "Random (television snow)", "snow" }, - { GST_VIDEOTESTSRC_BLACK, "0% Black", "black" }, - { 0, NULL, NULL }, - }; - - videotestsrc_pattern_type = - g_enum_register_static ("GstVideotestsrcPattern", - pattern_types); - } - - return videotestsrc_pattern_type; -} - -[..] - -static void -gst_videotestsrc_class_init (GstvideotestsrcClass *klass) -{ -[..] - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PATTERN, - g_param_spec_enum ("pattern", "Pattern", - "Type of test pattern to generate", - GST_TYPE_VIDEOTESTSRC_PATTERN, GST_VIDEOTESTSRC_SMPTE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -[..] -} - - diff --git a/docs/pwg/building-queryfn.xml b/docs/pwg/building-queryfn.xml deleted file mode 100644 index 2f8816318a..0000000000 --- a/docs/pwg/building-queryfn.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - The query function - - Through the query function, your element will receive queries that it - has to reply to. These are queries like position, duration but also - about the supported formats and scheduling modes your element supports. - Queries can travel both upstream and downstream, so you can receive them - on sink pads as well as source pads. - - - Below follows a very simple query function that we install on the source - pad of our element. - - -srcpad, - gst_my_filter_src_query); -[..] -} - -static gboolean -gst_my_filter_src_query (GstPad *pad, - GstObject *parent, - GstQuery *query) -{ - gboolean ret; - GstMyFilter *filter = GST_MY_FILTER (parent); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - /* we should report the current position */ - [...] - break; - case GST_QUERY_DURATION: - /* we should report the duration here */ - [...] - break; - case GST_QUERY_CAPS: - /* we should report the supported caps here */ - [...] - break; - default: - /* just call the default handler */ - ret = gst_pad_query_default (pad, parent, query); - break; - } - return ret; -} -]]> - - - It is a good idea to call the default query handler - gst_pad_query_default () for unknown queries. - Depending on the query type, the default handler will forward - the query or simply unref it. - - diff --git a/docs/pwg/building-signals.xml b/docs/pwg/building-signals.xml deleted file mode 100644 index 73be168e9c..0000000000 --- a/docs/pwg/building-signals.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - Signals - - GObject signals can be used to notify applications of events specific - to this object. Note, however, that the application needs to be aware - of signals and their meaning, so if you're looking for a generic way - for application-element interaction, signals are probably not what - you're looking for. In many cases, however, signals can be very useful. - See the GObject - documentation for all internals about signals. - - diff --git a/docs/pwg/building-state.xml b/docs/pwg/building-state.xml deleted file mode 100644 index f07ccefbbc..0000000000 --- a/docs/pwg/building-state.xml +++ /dev/null @@ -1,184 +0,0 @@ - - What are states? - - A state describes whether the element instance is initialized, whether it - is ready to transfer data and whether it is currently handling data. There - are four states defined in &GStreamer;: - - - - - GST_STATE_NULL - - - - - GST_STATE_READY - - - - - GST_STATE_PAUSED - - - - - GST_STATE_PLAYING - - - - - which will from now on be referred to simply as NULL, - READY, PAUSED and PLAYING. - - - GST_STATE_NULL is the default state of an element. In this state, it - has not allocated any runtime resources, it has not loaded any runtime - libraries and it can obviously not handle data. - - - GST_STATE_READY is the next state that an element can be in. In the - READY state, an element has all default resources (runtime-libraries, - runtime-memory) allocated. However, it has not yet allocated or defined - anything that is stream-specific. When going from NULL to READY state - (GST_STATE_CHANGE_NULL_TO_READY), an element should - allocate any non-stream-specific resources and should load runtime-loadable - libraries (if any). When going the other way around (from READY to NULL, - GST_STATE_CHANGE_READY_TO_NULL), an element should unload - these libraries and free all allocated resources. Examples of such - resources are hardware devices. Note that files are generally streams, - and these should thus be considered as stream-specific resources; therefore, - they should not be allocated in this state. - - - GST_STATE_PAUSED is the state in which an element is - ready to accept and handle data. For most elements this state is the same - as PLAYING. The only exception to this rule are sink elements. Sink - elements only accept one single buffer of data and then block. At this - point the pipeline is 'prerolled' and ready to render data immediately. - - - GST_STATE_PLAYING is the highest state that an element - can be in. For most elements this state is exactly the same as PAUSED, - they accept and process events and buffers with data. Only sink elements - need to differentiate between PAUSED and PLAYING state. In PLAYING state, - sink elements actually render incoming data, e.g. output audio to a sound - card or render video pictures to an image sink. - - - - Managing filter state - - If at all possible, your element should derive from one of the new base - classes (). There are ready-made - general purpose base classes for different types of sources, sinks and - filter/transformation elements. In addition to those, specialised base - classes exist for audio and video elements and others. - - - If you use a base class, you will rarely have to handle state changes - yourself. All you have to do is override the base class's start() and - stop() virtual functions (might be called differently depending on the - base class) and the base class will take care of everything for you. - - - If, however, you do not derive from a ready-made base class, but from - GstElement or some other class not built on top of a base class, you - will most likely have to implement your own state change function to - be notified of state changes. This is definitively necessary if your - plugin is a demuxer or a muxer, as there are no base classes for - muxers or demuxers yet. - - - An element can be notified of state changes through a virtual function - pointer. Inside this function, the element can initialize any sort of - specific data needed by the element, and it can optionally fail to - go from one state to another. - - - Do not g_assert for unhandled state changes; this is taken care of by - the GstElement base class. - - -static GstStateChangeReturn -gst_my_filter_change_state (GstElement *element, GstStateChange transition); - -static void -gst_my_filter_class_init (GstMyFilterClass *klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - element_class->change_state = gst_my_filter_change_state; -} - - - -static GstStateChangeReturn -gst_my_filter_change_state (GstElement *element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstMyFilter *filter = GST_MY_FILTER (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_my_filter_allocate_memory (filter)) - return GST_STATE_CHANGE_FAILURE; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - gst_my_filter_free_memory (filter); - break; - default: - break; - } - - return ret; -} - - - - Note that upwards (NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING) - and downwards (PLAYING=>PAUSED, PAUSED=>READY, READY=>NULL) state - changes are handled in two separate blocks with the downwards state change - handled only after we have chained up to the parent class's state - change function. This is necessary in order to safely handle concurrent - access by multiple threads. - - - The reason for this is that in the case of downwards state changes - you don't want to destroy allocated resources while your plugin's - chain function (for example) is still accessing those resources in - another thread. Whether your chain function might be running or not - depends on the state of your plugin's pads, and the state of those - pads is closely linked to the state of the element. Pad states are - handled in the GstElement class's state change function, including - proper locking, that's why it is essential to chain up before - destroying allocated resources. - - - diff --git a/docs/pwg/building-testapp.xml b/docs/pwg/building-testapp.xml deleted file mode 100644 index 43a16f9575..0000000000 --- a/docs/pwg/building-testapp.xml +++ /dev/null @@ -1,216 +0,0 @@ - - - - Building a Test Application - - Often, you will want to test your newly written plugin in an as small - setting as possible. Usually, gst-launch-1.0 is a - good first step at testing a plugin. If you have not installed your - plugin in a directory that GStreamer searches, then you will need to - set the plugin path. Either set GST_PLUGIN_PATH to the directory - containing your plugin, or use the command-line option --gst-plugin-path. - If you based your plugin off of the gst-plugin template, then this - will look something like - - gst-launch-1.0 --gst-plugin-path=$HOME/gst-template/gst-plugin/src/.libs TESTPIPELINE - - However, you will often need more - testing features than gst-launch-1.0 can provide, such as seeking, events, - interactivity and more. Writing your own small testing program is the - easiest way to accomplish this. This section explains - in a few words - - how to do that. For a complete application development guide, see the - Application Development - Manual. - - - - At the start, you need to initialize the &GStreamer; core library by - calling gst_init (). You can alternatively call - gst_init_get_option_group (), which will return - a pointer to GOptionGroup. You can then use GOption to handle the - initialization, and this will finish the &GStreamer; initialization. - - - - You can create elements using gst_element_factory_make (), - where the first argument is the element type that you want to create, - and the second argument is a free-form name. The example at the end uses - a simple filesource - decoder - soundcard output pipeline, but you can - use specific debugging elements if that's necessary. For example, an - identity element can be used in the middle of - the pipeline to act as a data-to-application transmitter. This can be - used to check the data for misbehaviours or correctness in your test - application. Also, you can use a fakesink - element at the end of the pipeline to dump your data to the stdout - (in order to do this, set the dump property to - TRUE). Lastly, you can use valgrind to check for memory errors. - - - - During linking, your test application can use filtered caps - as a way to drive a specific type of data to or from your element. This - is a very simple and effective way of checking multiple types of input - and output in your element. - - - - Note that during running, you should listen for at least the - error and eos messages on the bus - and/or your plugin/element to check for correct handling of this. Also, - you should add events into the pipeline and make sure your plugin handles - these correctly (with respect to clocking, internal caching, etc.). - - - - Never forget to clean up memory in your plugin or your test application. - When going to the NULL state, your element should clean up allocated - memory and caches. Also, it should close down any references held to - possible support libraries. Your application should unref () - the pipeline and make sure it doesn't crash. - - - -#include <gst/gst.h> - -static gboolean -bus_call (GstBus *bus, - GstMessage *msg, - gpointer data) -{ - GMainLoop *loop = 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 = NULL; - GError *err = NULL; - - gst_message_parse_error (msg, &err, &debug); - - g_print ("Error: %s\n", err->message); - g_error_free (err); - - if (debug) { - g_print ("Debug details: %s\n", debug); - g_free (debug); - } - - g_main_loop_quit (loop); - break; - } - default: - break; - } - - return TRUE; -} - -gint -main (gint argc, - gchar *argv[]) -{ - GstStateChangeReturn ret; - GstElement *pipeline, *filesrc, *decoder, *filter, *sink; - GstElement *convert1, *convert2, *resample; - GMainLoop *loop; - GstBus *bus; - guint watch_id; - - /* initialization */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - if (argc != 2) { - g_print ("Usage: %s <mp3 filename>\n", argv[0]); - return 01; - } - - /* create elements */ - pipeline = gst_pipeline_new ("my_pipeline"); - - /* watch for messages on the pipeline's bus (note that this will only - * work like this when a GLib main loop is running) */ - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - watch_id = gst_bus_add_watch (bus, bus_call, loop); - gst_object_unref (bus); - - filesrc = gst_element_factory_make ("filesrc", "my_filesource"); - decoder = gst_element_factory_make ("mad", "my_decoder"); - - /* putting an audioconvert element here to convert the output of the - * decoder into a format that my_filter can handle (we are assuming it - * will handle any sample rate here though) */ - convert1 = gst_element_factory_make ("audioconvert", "audioconvert1"); - - /* use "identity" here for a filter that does nothing */ - filter = gst_element_factory_make ("my_filter", "my_filter"); - - /* there should always be audioconvert and audioresample elements before - * the audio sink, since the capabilities of the audio sink usually vary - * depending on the environment (output used, sound card, driver etc.) */ - convert2 = gst_element_factory_make ("audioconvert", "audioconvert2"); - resample = gst_element_factory_make ("audioresample", "audioresample"); - sink = gst_element_factory_make ("pulsesink", "audiosink"); - - if (!sink || !decoder) { - g_print ("Decoder or output could not be found - check your install\n"); - return -1; - } else if (!convert1 || !convert2 || !resample) { - g_print ("Could not create audioconvert or audioresample element, " - "check your installation\n"); - return -1; - } else if (!filter) { - g_print ("Your self-written filter could not be found. Make sure it " - "is installed correctly in $(libdir)/gstreamer-1.0/ or " - "~/.gstreamer-1.0/plugins/ and that gst-inspect-1.0 lists it. " - "If it doesn't, check with 'GST_DEBUG=*:2 gst-inspect-1.0' for " - "the reason why it is not being loaded."); - return -1; - } - - g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); - - gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, convert1, filter, - convert2, resample, sink, NULL); - - /* link everything together */ - if (!gst_element_link_many (filesrc, decoder, convert1, filter, convert2, - resample, sink, NULL)) { - g_print ("Failed to link one or more elements!\n"); - return -1; - } - - /* run */ - ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - GstMessage *msg; - - g_print ("Failed to start up pipeline!\n"); - - /* check if there is an error message with details on the bus */ - msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0); - if (msg) { - GError *err = NULL; - - gst_message_parse_error (msg, &err, NULL); - g_print ("ERROR: %s\n", err->message); - g_error_free (err); - gst_message_unref (msg); - } - return -1; - } - - g_main_loop_run (loop); - - /* clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - g_source_remove (watch_id); - g_main_loop_unref (loop); - - return 0; -} - - diff --git a/docs/pwg/intro-basics.xml b/docs/pwg/intro-basics.xml deleted file mode 100644 index de065d27d3..0000000000 --- a/docs/pwg/intro-basics.xml +++ /dev/null @@ -1,395 +0,0 @@ - - - - Foundations - - This chapter of the guide introduces the basic concepts of &GStreamer;. - Understanding these concepts will help you grok the issues involved in - extending &GStreamer;. Many of these concepts are explained in greater - detail in the &GstAppDevMan;; the basic concepts presented here serve mainly - to refresh your memory. - - - - - - Elements and Plugins - - Elements are at the core of &GStreamer;. In the context of plugin - development, an element is an object derived from the - - GstElement class. Elements provide some sort of - functionality when linked with other elements: For example, a source - element provides data to a stream, and a filter element acts on the data - in a stream. Without elements, &GStreamer; is just a bunch of conceptual - pipe fittings with nothing to link. A large number of elements ship - with &GStreamer;, but extra elements can also be written. - - - Just writing a new element is not entirely enough, however: You will need - to encapsulate your element in a plugin to enable - &GStreamer; to use it. A plugin is essentially a loadable block of code, - usually called a shared object file or a dynamically linked library. A - single plugin may contain the implementation of several elements, or just - a single one. For simplicity, this guide concentrates primarily on plugins - containing one element. - - - A filter is an important type of element that - processes a stream of data. Producers and consumers of data are called - source and sink elements, - respectively. Bin elements contain other elements. - One type of bin is responsible for synchronization of the elements that they - contain so that data flows smoothly. Another type of bin, called - autoplugger elements, automatically add other - elements to the bin and links them together so that they act as a - filter between two arbitrary stream types. - - - The plugin mechanism is used everywhere in &GStreamer;, even if only the - standard packages are being used. A few very basic functions reside in the - core library, and all others are implemented in plugins. A plugin registry - is used to store the details of the plugins in an binary registry file. - This way, a program using &GStreamer; does not have to load all plugins to - determine which are needed. Plugins are only loaded when their provided - elements are requested. - - - See the &GstLibRef; for the current implementation details of GstElement - and GstPlugin. - - - - - - - Pads - - Pads are used to negotiate links and data flow - between elements in &GStreamer;. A pad can be viewed as a - place or port on an element where - links may be made with other elements, and through which data can - flow to or from those elements. Pads have specific data handling - capabilities: A pad can restrict the type of data that flows - through it. Links are only allowed between two pads when the - allowed data types of the two pads are compatible. - - - An analogy may be helpful here. A pad is similar to a plug or jack on a - physical device. Consider, for example, a home theater system consisting - of an amplifier, a DVD player, and a (silent) video projector. Linking - the DVD player to the amplifier is allowed because both devices have audio - jacks, and linking the projector to the DVD player is allowed because - both devices have compatible video jacks. Links between the - projector and the amplifier may not be made because the projector and - amplifier have different types of jacks. Pads in &GStreamer; serve the - same purpose as the jacks in the home theater system. - - - For the most part, all data in &GStreamer; flows one way through a link - between elements. Data flows out of one element through one or more - source pads, and elements accept incoming data through - one or more sink pads. Source and sink elements have - only source and sink pads, respectively. - - - See the &GstLibRef; for the current implementation details of a GstPad. - - - - - - - GstMiniObject, Buffers and Events - - All streams of data in &GStreamer; are chopped up into chunks that are - passed from a source pad on one element to a sink pad on another element. - GstMiniObject is the structure used to hold these - chunks of data. - - - GstMiniObject contains the following important types: - - - - An exact type indicating what type of data (event, buffer, ...) - this GstMiniObject is. - - - - - A reference count indicating the number of elements currently - holding a reference to the miniobject. When the reference count - falls to zero, the miniobject will be disposed, and its memory will be - freed in some sense (see below for more details). - - - - - - For data transport, there are two types of GstMiniObject defined: - events (control) and buffers (content). - - - Buffers may contain any sort of data that the two linked pads - know how to handle. Normally, a buffer contains a chunk of some sort of - audio or video data that flows from one element to another. - - - Buffers also contain metadata describing the buffer's contents. Some of - the important types of metadata are: - - - - Pointers to one or more GstMemory objects. GstMemory objects are - refcounted objects that encapsulate a region of memory. - - - - - A timestamp indicating the preferred display timestamp of the - content in the buffer. - - - - - - Events - contain information on the state of the stream flowing between the two - linked pads. Events will only be sent if the element explicitly supports - them, else the core will (try to) handle the events automatically. Events - are used to indicate, for example, a media type, the end of a - media stream or that the cache should be flushed. - - - Events may contain several of the following items: - - - - A subtype indicating the type of the contained event. - - - - - The other contents of the event depend on the specific event type. - - - - - - Events will be discussed extensively in . - Until then, the only event that will be used is the EOS - event, which is used to indicate the end-of-stream (usually end-of-file). - - - See the &GstLibRef; for the current implementation details of a GstMiniObject, GstBuffer and GstEvent. - - - - Buffer Allocation - - Buffers are able to store chunks of memory of several different - types. The most generic type of buffer contains memory allocated - by malloc(). Such buffers, although convenient, are not always - very fast, since data often needs to be specifically copied into - the buffer. - - - Many specialized elements create buffers that point to special - memory. For example, the filesrc element usually - maps a file into the address space of the application (using mmap()), - and creates buffers that point into that address range. These - buffers created by filesrc act exactly like generic buffers, except - that they are read-only. The buffer freeing code automatically - determines the correct method of freeing the underlying memory. - Downstream elements that receive these kinds of buffers do not - need to do anything special to handle or unreference it. - - - Another way an element might get specialized buffers is to - request them from a downstream peer through a GstBufferPool or - GstAllocator. Elements can ask a GstBufferPool or GstAllocator - from the downstream peer element. If downstream is able to provide - these objects, upstream can use them to allocate buffers. - See more in . - - - Many sink elements have accelerated methods for copying data - to hardware, or have direct access to hardware. It is common - for these elements to be able to create a GstBufferPool or - GstAllocator for their upstream peers. One such example is - ximagesink. It creates buffers that contain XImages. Thus, - when an upstream peer copies data into the buffer, it is copying - directly into the XImage, enabling ximagesink to draw the - image directly to the screen instead of having to copy data - into an XImage first. - - - Filter elements often have the opportunity to either work on - a buffer in-place, or work while copying from a source buffer - to a destination buffer. It is optimal to implement both - algorithms, since the &GStreamer; framework can choose the - fastest algorithm as appropriate. Naturally, this only makes - sense for strict filters -- elements that have exactly the - same format on source and sink pads. - - - - - - - - Media types and Properties - - &GStreamer; uses a type system to ensure that the data passed between - elements is in a recognized format. The type system is also important - for ensuring that the parameters required to fully specify a format match - up correctly when linking pads between elements. Each link that is - made between elements has a specified type and optionally a set of - properties. See more about caps negotiation in - . - - - - - - The Basic Types - - &GStreamer; already supports many basic media types. Following is a - table of a few of the basic types used for buffers in - &GStreamer;. The table contains the name ("media type") and a - description of the type, the properties associated with the type, and - the meaning of each property. A full list of supported types is - included in . - - - - Table of Example Types - - - - - Media Type - Description - Property - Property Type - Property Values - Property Description - - - - - - - - - audio/* - - All audio types - - rate - integer - greater than 0 - - The sample rate of the data, in samples (per channel) per second. - - - - channels - integer - greater than 0 - - The number of channels of audio data. - - - - - - - audio/x-raw - - Unstructured and uncompressed raw integer audio data. - - format - string - - 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 - - - The format of the sample data. - - - - - - - audio/mpeg - - Audio data compressed using the MPEG audio encoding scheme. - - mpegversion - integer - 1, 2 or 4 - - The MPEG-version used for encoding the data. The value 1 refers - to MPEG-1, -2 and -2.5 layer 1, 2 or 3. The values 2 and 4 refer - to the MPEG-AAC audio encoding schemes. - - - - framed - boolean - 0 or 1 - - A true value indicates that each buffer contains exactly one - frame. A false value indicates that frames and buffers do not - necessarily match up. - - - - layer - integer - 1, 2, or 3 - - The compression scheme layer used to compress the data - (only if mpegversion=1). - - - - bitrate - integer - greater than 0 - - The bitrate, in bits per second. For VBR (variable bitrate) - MPEG data, this is the average bitrate. - - - - - - - audio/x-vorbis - Vorbis audio data - - - - - There are currently no specific properties defined for this type. - - - - -
-
-
-
diff --git a/docs/pwg/intro-preface.xml b/docs/pwg/intro-preface.xml deleted file mode 100644 index 40e6541ee1..0000000000 --- a/docs/pwg/intro-preface.xml +++ /dev/null @@ -1,296 +0,0 @@ - - - - - Preface - - - - - What is &GStreamer;? - - &GStreamer; is a framework for creating streaming media applications. - The fundamental design comes from the video pipeline at Oregon Graduate - Institute, as well as some ideas from DirectShow. - - - - &GStreamer;'s development framework makes it possible to write any - type of streaming multimedia application. The &GStreamer; framework - is designed to make it easy to write applications that handle audio - or video or both. It isn't restricted to audio and video, and can - process any kind of data flow. - The pipeline design is made to have little overhead above what the - applied filters induce. This makes &GStreamer; a good framework for - designing even high-end audio applications which put high demands on - latency or performance. - - - - One of the most obvious uses of &GStreamer; is using it to build - a media player. &GStreamer; already includes components for building a - media player that can support a very wide variety of formats, including - MP3, Ogg/Vorbis, MPEG-1/2, AVI, Quicktime, mod, and more. &GStreamer;, - however, is much more than just another media player. Its main advantages - are that the pluggable components can be mixed and matched into arbitrary - pipelines so that it's possible to write a full-fledged video or audio - editing application. - - - - The framework is based on plugins that will provide the various codec - and other functionality. The plugins can be linked and arranged in - a pipeline. This pipeline defines the flow of the data. - - - - The &GStreamer; core function is to provide a framework for plugins, - data flow, synchronization and media type handling/negotiation. It - also provides an API to write applications using the various plugins. - - - - - - - Who Should Read This Guide? - - This guide explains how to write new modules for &GStreamer;. The guide is - relevant to several groups of people: - - - - - Anyone who wants to add support for new ways of processing data in - &GStreamer;. For example, a person in this group might want to create - a new data format converter, a new visualization tool, or a new - decoder or encoder. - - - - - Anyone who wants to add support for new input and output devices. For - example, people in this group might want to add the ability to write - to a new video output system or read data from a digital camera or - special microphone. - - - - - Anyone who wants to extend &GStreamer; in any way. You need to have an - understanding of how the plugin system works before you can understand - the constraints that the plugin system places on the rest of the code. - Also, you might be surprised after reading this at how much can be - done with plugins. - - - - - This guide is not relevant to you if you only want to use the existing - functionality of &GStreamer;, or if you just want to use an application - that uses &GStreamer;. If you are only interested in using existing - plugins to write a new application - and there are quite a lot of - plugins already - you might want to check the &GstAppDevMan;. If you - are just trying to get help with a &GStreamer; application, then you - should check with the user manual for that particular application. - - - - - - - Preliminary Reading - - This guide assumes that you are somewhat familiar with the basic workings - of &GStreamer;. For a gentle introduction to programming concepts in - &GStreamer;, you may wish to read the &GstAppDevMan; first. - Also check out the other documentation available on the &GStreamer; web site. - - - In order to understand this manual, you will need to have a basic - understanding of the C language. - Since &GStreamer; adheres to the GObject programming model, this guide - also assumes that you understand the basics of GObject - programming. - You may also want to have a look - at Eric Harlow's book Developing Linux Applications with - GTK+ and GDK. - - - - - - - Structure of This Guide - - To help you navigate through this guide, it is divided into several large - parts. Each part addresses a particular broad topic concerning &GStreamer; - plugin development. The parts of this guide are laid out in the following - order: - - - - - - - Introduction to the structure of a plugin, using an example audio - filter for illustration. - - - This part covers all the basic steps you generally need to perform - to build a plugin, such as registering the element with &GStreamer; - and setting up the basics so it can receive data from and send data - to neighbour elements. The discussion begins by giving examples of - generating the basic structures and registering an element in - . Then, you will learn how - to write the code to get a basic filter plugin working in , and . - - - After that, we will show some of the GObject concepts on how to - make an element configurable for applications and how to do - application-element interaction in - and . Next, you will learn to build - a quick test application to test all that you've just learned in - . We will just touch upon - basics here. For full-blown application development, you should - look at the - Application Development Manual. - - - - - - - Information on advanced features of &GStreamer; plugin development. - - - After learning about the basic steps, you should be able to create a - functional audio or video filter plugin with some nice features. - However, &GStreamer; offers more for plugin writers. This part of the - guide includes chapters on more advanced topics, such as scheduling, - media type definitions in &GStreamer;, clocks, interfaces and - tagging. Since these features are purpose-specific, you can read them - in any order, most of them don't require knowledge from other - sections. - - - The first chapter, named , - will explain some of the basics of element scheduling. It is not - very in-depth, but is mostly some sort of an introduction on why - other things work as they do. Read this chapter if you're interested - in &GStreamer; internals. Next, we will apply this knowledge and - discuss another type of data transmission than what you learned in - : . Loop-based elements will give - you more control over input rate. This is useful when writing, for - example, muxers or demuxers. - - - Next, we will discuss media identification in &GStreamer; in . You will learn how to define - new media types and get to know a list of standard media types - defined in &GStreamer;. - - - In the next chapter, you will learn the concept of request- and - sometimes-pads, which are pads that are created dynamically, either - because the application asked for it (request) or because the media - stream requires it (sometimes). This will be in . - - - The next chapter, , will - explain the concept of clocks in &GStreamer;. You need this - information when you want to know how elements should achieve - audio/video synchronization. - - - The next few chapters will discuss advanced ways of doing - application-element interaction. Previously, we learned on the - GObject-ways of doing this in - and . We will discuss - dynamic parameters, which are a way of defining element behaviour - over time in advance, in . Next, - you will learn about interfaces in . Interfaces are very target- - specific ways of application-element interaction, based on GObject's - GInterface. Lastly, you will learn about how metadata is handled in - &GStreamer; in . - - - The last chapter, , will - discuss the concept of events in &GStreamer;. Events are, on the - one hand, another way of doing application-element interaction. It - takes care of seeking, for example. On the other hand, it is also - a way in which elements interact with each other, such as letting - each other know about media stream discontinuities, forwarding tags - inside a pipeline and so on. - - - - - - Explanation - of writing other plugin types. - - - Because the first two parts of the guide use an audio filter as an - example, the concepts introduced apply to filter plugins. But many of - the concepts apply equally to other plugin types, including sources, - sinks, and autopluggers. This part of the guide presents the issues - that arise when working on these more specialized plugin types. The - chapter starts with a special focus on elements that can be written - using a base-class (), and - later also goes into writing special types of elements in - , and . - - - - - - Further - information for plugin developers. - - - The appendices contain some information that stubbornly refuses - to fit cleanly in other sections of the guide. Most of this section - is not yet finished. - - - - - - The remainder of this introductory part of the guide presents a short - overview of the basic concepts involved in &GStreamer; plugin development. - Topics covered include , , and - . If you are already familiar with - this information, you can use this short overview to refresh your memory, - or you can skip to . - - - As you can see, there a lot to learn, so let's get started! - - - - - - Creating compound and complex elements by extending from a GstBin. - This will allow you to create plugins that have other plugins embedded - in them. - - - - - Adding new media types to the registry along with typedetect functions. - This will allow your plugin to operate on a completely new media type. - - - - - diff --git a/docs/pwg/other-base.xml b/docs/pwg/other-base.xml deleted file mode 100644 index 0c00f98117..0000000000 --- a/docs/pwg/other-base.xml +++ /dev/null @@ -1,310 +0,0 @@ - - Pre-made base classes - - So far, we've been looking at low-level concepts of creating any type of - &GStreamer; element. Now, let's assume that all you want is to create an - simple audiosink that works exactly the same as, say, - esdsink, or a filter that simply normalizes audio volume. - Such elements are very general in concept and since they do nothing - special, they should be easier to code than to provide your own scheduler - activation functions and doing complex caps negotiation. For this purpose, - &GStreamer; provides base classes that simplify some types of elements. - Those base classes will be discussed in this chapter. - - - - Writing a sink - - 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. - - - The base class implement much of the synchronization logic that a - sink has to perform. - - - The GstBaseSink base-class specifies some - limitations on elements, though: - - - - - It requires that the sink only has one sinkpad. Sink elements that - need more than one sinkpad, must make a manager element with - multiple GstBaseSink elements inside. - - - - - Sink elements can derive from GstBaseSink using - the usual GObject convenience macro - G_DEFINE_TYPE (): - - -G_DEFINE_TYPE (GstMySink, gst_my_sink, GST_TYPE_BASE_SINK); - -[..] - -static void -gst_my_sink_class_init (GstMySinkClass * klass) -{ - klass->set_caps = [..]; - klass->render = [..]; -[..] -} - - - The advantages of deriving from GstBaseSink are - numerous: - - - - - Derived implementations barely need to be aware of preroll, and do - not need to know anything about the technical implementation - requirements of preroll. The base-class does all the hard work. - - - Less code to write in the derived class, shared code (and thus - shared bugfixes). - - - - - There are also specialized base classes for audio and video, let's look - at those a bit. - - - - Writing an audio sink - - Essentially, audio sink implementations are just a special case of a - general sink. An audio sink has the added complexity that it needs to - schedule playback of samples. It must match the clock selected in the - pipeline against the clock of the audio device and calculate and - compensate for drift and jitter. - - - There are two audio base classes that you can choose to - derive from, depending on your needs: - GstAudioBasesink and - GstAudioSink. The audiobasesink provides full - control over how synchronization and scheduling is handled, by using - a ringbuffer that the derived class controls and provides. The - audiosink base-class is a derived class of the audiobasesink, - implementing a standard ringbuffer implementing default - synchronization and providing a standard audio-sample clock. Derived - classes of this base class merely need to provide a _open - (), _close () and a _write - () function implementation, and some optional functions. - This should suffice for many sound-server output elements and even - most interfaces. More demanding audio systems, such as Jack, would - want to implement the GstAudioBaseSink - base-class. - - - The GstAudioBaseSink has little to no - limitations and should fit virtually every implementation, but is - hard to implement. The GstAudioSink, on the - other hand, only fits those systems with a simple open - () / close () / write - () API (which practically means pretty much all of them), - but has the advantage that it is a lot easier to implement. The - benefits of this second base class are large: - - - - - Automatic synchronization, without any code in the derived class. - - - - - Also automatically provides a clock, so that other sinks (e.g. in - case of audio/video playback) are synchronized. - - - - - Features can be added to all audiosinks by making a change in the - base class, which makes maintenance easy. - - - - - Derived classes require only three small functions, plus some - GObject boilerplate code. - - - - - In addition to implementing the audio base-class virtual functions, - derived classes can (should) also implement the - GstBaseSink set_caps () and - get_caps () virtual functions for negotiation. - - - - - Writing a video sink - - Writing a videosink can be done using the - GstVideoSink base-class, which derives from - GstBaseSink internally. Currently, it does - nothing yet but add another compile dependency, so derived classes - will need to implement all base-sink virtual functions. When they do - this correctly, this will have some positive effects on the end user - experience with the videosink: - - - - - Because of preroll (and the preroll () virtual - function), it is possible to display a video frame already when - going into the GST_STATE_PAUSED state. - - - - - By adding new features to GstVideoSink, it - will be possible to add extensions to videosinks that affect all of - them, but only need to be coded once, which is a huge maintenance - benefit. - - - - - - - - Writing a source - - In the previous part, particularly , we have learned that some types - of elements can provide random access. This applies most definitely to - source elements reading from a randomly seekable location, such as file - sources. However, other source elements may be better described as a - live source element, such as a camera source, an audio card source and - such; those are not seekable and do not provide byte-exact access. For - all such use cases, &GStreamer; provides two base classes: - GstBaseSrc for the basic source functionality, and - GstPushSrc, which is a non-byte exact source - base-class. The pushsource base class itself derives from basesource as - well, and thus all statements about the basesource apply to the - pushsource, too. - - - The basesrc class does several things automatically for derived classes, - so they no longer have to worry about it: - - - - - Fixes to GstBaseSrc apply to all derived - classes automatically. - - - - - Automatic pad activation handling, and task-wrapping in case we get - assigned to start a task ourselves. - - - - - The GstBaseSrc may not be suitable for all cases, - though; it has limitations: - - - - - There is one and only one sourcepad. Source elements requiring - multiple sourcepads must implement a manager bin and use multiple - source elements internally or make a manager element that uses - a source element and a demuxer inside. - - - - - It is possible to use special memory, such as X server memory pointers - or mmap ()'ed memory areas, as data pointers in - buffers returned from the create() virtual function. - - - - Writing an audio source - - An audio source is nothing more but a special case of a pushsource. - Audio sources would be anything that reads audio, such as a source - reading from a soundserver, a kernel interface (such as ALSA) or a - test sound / signal generator. &GStreamer; provides two base classes, - similar to the two audiosinks described in ; one is ringbuffer-based, and - requires the derived class to take care of its own scheduling, - synchronization and such. The other is based on this - GstAudioBaseSrc and is called - GstAudioSrc, and provides a simple - open (), close () and - read () interface, which is rather simple to - implement and will suffice for most soundserver sources and audio - interfaces (e.g. ALSA or OSS) out there. - - - The GstAudioSrc base-class has several benefits - for derived classes, on top of the benefits of the - GstPushSrc base-class that it is based on: - - - - - Does syncronization and provides a clock. - - - - - New features can be added to it and will apply to all derived - classes automatically. - - - - - - - - Writing a transformation element - - A third base-class that &GStreamer; provides is the - GstBaseTransform. This is a base class for - elements with one sourcepad and one sinkpad which act as a filter - of some sort, such as volume changing, audio resampling, audio format - conversion, and so on and so on. There is quite a lot of bookkeeping - that such elements need to do in order for things such as buffer - allocation forwarding, passthrough, in-place processing and such to all - work correctly. This base class does all that for you, so that you just - need to do the actual processing. - - - Since the GstBaseTransform is based on the 1-to-1 - model for filters, it may not apply well to elements such as decoders, - which may have to parse properties from the stream. Also, it will not - work for elements requiring more than one sourcepad or sinkpad. - - - diff --git a/docs/pwg/other-manager.xml b/docs/pwg/other-manager.xml deleted file mode 100644 index 53381146bf..0000000000 --- a/docs/pwg/other-manager.xml +++ /dev/null @@ -1,46 +0,0 @@ - - Writing a Manager - - Managers are elements that add a function or unify the function of - another (series of) element(s). Managers are generally a - GstBin with one or more ghostpads. Inside them - is/are the actual element(s) that matters. There is several cases where - this is useful. For example: - - - - - To add support for private events with custom event handling to - another element. - - - - - To add support for custom pad _query () - or _convert () handling to another element. - - - - - To add custom data handling before or after another element's data - handler function (generally its _chain () - function). - - - - - To embed an element, or a series of elements, into something that - looks and works like a simple element to the outside world. This - is particular handy for implementing sources and sink elements with - multiple pads. - - - - - Making a manager is about as simple as it gets. You can derive from a - GstBin, and in most cases, you can embed the - required elements in the _init () already, including - setup of ghostpads. If you need any custom data handlers, you can connect - signals or embed a second element which you control. - - diff --git a/docs/pwg/other-ntoone.xml b/docs/pwg/other-ntoone.xml deleted file mode 100644 index 9efcff63af..0000000000 --- a/docs/pwg/other-ntoone.xml +++ /dev/null @@ -1,155 +0,0 @@ - - Writing a N-to-1 Element or Muxer - - N-to-1 elements have been previously mentioned and discussed in both - and in - . The main noteworthy thing - about N-to-1 elements is that each pad is push-based in its own thread, - and the N-to-1 element synchronizes those streams by - expected-timestamp-based logic. This means it lets all streams wait - except for the one that provides the earliest next-expected timestamp. - When that stream has passed one buffer, the next - earliest-expected-timestamp is calculated, and we start back where we - were, until all streams have reached EOS. There is a helper base class, - called GstCollectPads, that will help you to do - this. - - - Note, however, that this helper class will only help you with grabbing - a buffer from each input and giving you the one with earliest timestamp. - If you need anything more difficult, such as "don't-grab-a-new-buffer - until a given timestamp" or something like that, you'll need to do this - yourself. - - - - diff --git a/docs/pwg/other-oneton.xml b/docs/pwg/other-oneton.xml deleted file mode 100644 index bc61bac4ff..0000000000 --- a/docs/pwg/other-oneton.xml +++ /dev/null @@ -1,45 +0,0 @@ - - Writing a Demuxer or Parser - - Demuxers are the 1-to-N elements that need very special care. - They are responsible for timestamping raw, unparsed data into - elementary video or audio streams, and there are many things that you - can optimize or do wrong. Here, several culprits will be mentioned - and common solutions will be offered. Parsers are demuxers with only - one source pad. Also, they only cut the stream into buffers, they - don't touch the data otherwise. - - - As mentioned previously in , - demuxers should use fixed caps, since their data type will not change. - - - As discussed in , demuxer elements - can be written in multiple ways: - - - - - They can be the driving force of the pipeline, by running their own - task. This works particularly well for elements that need random - access, for example an AVI demuxer. - - - - - They can also run in push-based mode, which means that an upstream - element drives the pipeline. This works particularly well for streams - that may come from network, such as Ogg. - - - - - In addition, audio parsers with one output can, in theory, also be written - in random access mode. Although simple playback will mostly work if your - element only accepts one mode, it may be required to implement multiple - modes to work in combination with all sorts of applications, such as - editing. Also, performance may become better if you implement multiple - modes. See to see how an element - can accept multiple scheduling modes. - - diff --git a/docs/pwg/other-sink.xml b/docs/pwg/other-sink.xml deleted file mode 100644 index 3222106838..0000000000 --- a/docs/pwg/other-sink.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Writing a Sink - - Sinks are output elements that, opposite to sources, have no source - pads and one or more (usually one) sink pad. They can be sound card - outputs, disk writers, etc. This chapter will discuss the basic - implementation of sink elements. - - - - Data processing, events, synchronization and clocks - - Except for corner cases, sink elements will be _chain - ()-based elements. The concept of such elements has - been discussed before in detail, so that will be skipped here. What - is very important in sink elements, specifically in real-time audio - and video sources (such as osssink or - ximagesink), is event handling in the - _chain ()-function, because most elements rely - on EOS-handling of the sink element, and because A/V synchronization - can only be perfect if the element takes this into account. - - - How to achieve synchronization between streams depends on whether - you're a clock-providing or a clock-receiving element. If you're - the clock provider, you can do with time whatever you want. Correct - handling would mean that you check whether the end of the previous - buffer (if any) and the start of the current buffer are the same. - If so, there's no gap between the two and you can continue playing - right away. If there is a gap, then you'll need to wait for your - clock to reach that time. How to do that depends on the element - type. In the case of audio output elements, you would output silence - for a while. In the case of video, you would show background color. - In case of subtitles, show no subtitles at all. - - - In the case that the provided clock and the received clock are not - the same (or in the case where your element provides no clock, which - is the same), you simply wait for the clock to reach the timestamp of - the current buffer and then you handle the data in it. - - - A simple data handling function would look like this: - - -static void -gst_my_sink_chain (GstPad *pad, - GstData *data) -{ - GstMySink *sink = GST_MY_SINK (gst_pad_get_parent (pad)); - GstBuffer *buf; - GstClockTime time; - - /* only needed if the element is GST_EVENT_AWARE */ - if (GST_IS_EVENT (data)) { - GstEvent *event = GST_EVENT (data); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - [ if your element provides a clock, disable (inactivate) it here ] - /* pass-through */ - - default: - /* the default handler handles discontinuities, even if your - * element provides a clock! */ - gst_pad_event_default (pad, event); - break; - } - - return; - } - - buf = GST_BUFFER (data); - if (GST_BUFFER_TIME_IS_VALID (buf)) - time = GST_BUFFER_TIMESTAMP (buf); - else - time = sink->expected_next_time; - - /* Synchronization - the property is only useful in case the - * element has the option of not syncing. So it is not useful - * for hardware-sync (clock-providing) elements. */ - if (sink->sync) { - /* This check is only needed if you provide a clock. Else, - * you can always execute the 'else' clause. */ - if (sink->provided_clock == sink->received_clock) { - /* GST_SECOND / 10 is 0,1 sec, it's an arbitrary value. The - * casts are needed because else it'll be unsigned and we - * won't detect negative values. */ - if (llabs ((gint64) sink->expected_next_time - (gint64) time) > - (GST_SECOND / 10)) { - /* so are we ahead or behind? */ - if (time > sink->expected_time) { - /* we need to wait a while... In case of audio, output - * silence. In case of video, output background color. - * In case of subtitles, display nothing. */ - [..] - } else { - /* Drop data. */ - [..] - } - } - } else { - /* You could do more sophisticated things here, but we'll - * keep it simple for the purpose of the example. */ - gst_element_wait (GST_ELEMENT (sink), time); - } - } - - /* And now handle the data. */ -[..] -} - - - - - Special memory - - Like source elements, sink elements can sometimes provide externally - allocated (such as X-provided or DMA'able) memory to elements earlier - in the pipeline, and thereby prevent the need for - memcpy () for incoming data. We do this by - providing a pad-allocate-buffer function. - - -static GstBuffer * gst_my_sink_buffer_allocate (GstPad *pad, - guint64 offset, - guint size); - -static void -gst_my_sink_init (GstMySink *sink) -{ -[..] - gst_pad_set_bufferalloc_function (sink->sinkpad, - gst_my_sink_buffer_allocate); -} - -static void -gst_my_sink_buffer_free (GstBuffer *buf) -{ - GstMySink *sink = GST_MY_SINK (GST_BUFFER_PRIVATE (buf)); - - /* Do whatever is needed here. */ -[..] -} - -static GstBuffer * -gst_my_sink_buffer_allocate (GstPad *pad, - guint64 offset, - guint size) -{ - GstBuffer *buf = gst_buffer_new (); - - /* So here it's up to you to wrap your private buffers and - * return that. */ - GST_BUFFER_FREE_DATA_FUNC (buf) = gst_my_sink_buffer_free; - GST_BUFFER_PRIVATE (buf) = sink; - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE); -[..] - - return buf; -} - - - diff --git a/docs/pwg/other-source.xml b/docs/pwg/other-source.xml deleted file mode 100644 index 55aaafc7de..0000000000 --- a/docs/pwg/other-source.xml +++ /dev/null @@ -1,475 +0,0 @@ - - - - - Writing a Source - - Source elements are the start of a data streaming pipeline. Source - elements have no sink pads and have one or more source pads. We will - focus on single-sourcepad elements here, but the concepts apply equally - well to multi-sourcepad elements. This chapter will explain the essentials - of source elements, which features it should implement and which it - doesn't have to, and how source elements will interact with other - elements in a pipeline. - - - - The get()-function - - Source elements have the special option of having a - _get ()-function rather than a - _loop ()- or _chain - ()-function. A _get ()-function is - called by the scheduler every time the next elements needs data. Apart - from corner cases, every source element will want to be _get - ()-based. - - -static GstData * gst_my_source_get (GstPad *pad); - -static void -gst_my_source_init (GstMySource *src) -{ -[..] - gst_pad_set_get_function (src->srcpad, gst_my_source_get); -} - -static GstData * -gst_my_source_get (GstPad *pad) -{ - GstBuffer *buffer; - - buffer = gst_buffer_new (); - GST_BUFFER_DATA (buf) = g_strdup ("hello pipeline!"); - GST_BUFFER_SIZE (buf) = strlen (GST_BUFFER_DATA (buf)); - /* terminating '/0' */ - GST_BUFFER_MAZSIZE (buf) = GST_BUFFER_SIZE (buf) + 1; - - return GST_DATA (buffer); -} - - - - - Events, querying and converting - - One of the most important functions of source elements is to - implement correct query, convert and event handling functions. - Those will continuously describe the current state of the stream. - Query functions can be used to get stream properties such as current - position and length. This can be used by fellow elements to convert - this same value into a different unit, or by applications to provide - information about the length/position of the stream to the user. - Conversion functions are used to convert such values from one unit - to another. Lastly, events are mostly used to seek to positions - inside the stream. Any function is essentially optional, but the - element should try to provide as much information as it knows. Note - that elements providing an event function should also list their - supported events in an _get_event_mask () - function. Elements supporting query operations should list the - supported operations in a _get_query_types - () function. Elements supporting either conversion - or query operations should also implement a _get_formats - () function. - - - An example source element could, for example, be an element that - continuously generates a wave tone at 44,1 kHz, mono, 16-bit. This - element will generate 44100 audio samples per second or 88,2 kB/s. - This information can be used to implement such functions: - - -static GstFormat * gst_my_source_format_list (GstPad *pad); -static GstQueryType * gst_my_source_query_list (GstPad *pad); - -static gboolean gst_my_source_convert (GstPad *pad, - GstFormat from_fmt, - gint64 from_val, - GstFormat *to_fmt, - gint64 *to_val); -static gboolean gst_my_source_query (GstPad *pad, - GstQueryType type, - GstFormat *to_fmt, - gint64 *to_val); - -static void -gst_my_source_init (GstMySource *src) -{ -[..] - gst_pad_set_convert_function (src->srcpad, gst_my_source_convert); - gst_pad_set_formats_function (src->srcpad, gst_my_source_format_list); - gst_pad_set_query_function (src->srcpad, gst_my_source_query); - gst_pad_set_query_type_function (src->srcpad, gst_my_source_query_list); -} - -/* - * This function returns an enumeration of supported GstFormat - * types in the query() or convert() functions. See gst/gstformat.h - * for a full list. - */ - -static GstFormat * -gst_my_source_format_list (GstPad *pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_TIME, - GST_FORMAT_DEFAULT, /* means "audio samples" */ - GST_FORMAT_BYTES, - 0 - }; - - return formats; -} - -/* - * This function returns an enumeration of the supported query() - * operations. Since we generate audio internally, we only provide - * an indication of how many samples we've played so far. File sources - * or such elements could also provide GST_QUERY_TOTAL for the total - * stream length, or other things. See gst/gstquery.h for details. - */ - -static GstQueryType * -gst_my_source_query_list (GstPad *pad) -{ - static const GstQueryType query_types[] = { - GST_QUERY_POSITION, - 0, - }; - - return query_types; -} - -/* - * And below are the logical implementations. - */ - -static gboolean -gst_my_source_convert (GstPad *pad, - GstFormat from_fmt, - gint64 from_val, - GstFormat *to_fmt, - gint64 *to_val) -{ - gboolean res = TRUE; - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - - switch (from_fmt) { - case GST_FORMAT_TIME: - switch (*to_fmt) { - case GST_FORMAT_TIME: - /* nothing */ - break; - - case GST_FORMAT_BYTES: - *to_val = from_val / (GST_SECOND / (44100 * 2)); - break; - - case GST_FORMAT_DEFAULT: - *to_val = from_val / (GST_SECOND / 44100); - break; - - default: - res = FALSE; - break; - } - break; - - case GST_FORMAT_BYTES: - switch (*to_fmt) { - case GST_FORMAT_TIME: - *to_val = from_val * (GST_SECOND / (44100 * 2)); - break; - - case GST_FORMAT_BYTES: - /* nothing */ - break; - - case GST_FORMAT_DEFAULT: - *to_val = from_val / 2; - break; - - default: - res = FALSE; - break; - } - break; - - case GST_FORMAT_DEFAULT: - switch (*to_fmt) { - case GST_FORMAT_TIME: - *to_val = from_val * (GST_SECOND / 44100); - break; - - case GST_FORMAT_BYTES: - *to_val = from_val * 2; - break; - - case GST_FORMAT_DEFAULT: - /* nothing */ - break; - - default: - res = FALSE; - break; - } - break; - - default: - res = FALSE; - break; - } - - return res; -} - -static gboolean -gst_my_source_query (GstPad *pad, - GstQueryType type, - GstFormat *to_fmt, - gint64 *to_val) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - gboolean res = TRUE; - - switch (type) { - case GST_QUERY_POSITION: - res = gst_pad_convert (pad, GST_FORMAT_BYTES, src->total_bytes, - to_fmt, to_val); - break; - - default: - res = FALSE; - break; - } - - return res; -} - - - Be sure to increase src->total_bytes after each call to your - _get () function. - - - Event handling has already been explained previously in the events - chapter. - - - - - Time, clocking and synchronization - - The above example does not provide any timing info, but will suffice - for elementary data sources such as a file source or network data - source element. Things become slightly more complicated, but still - very simple, if we create artificial video or audio data sources, - such as a video test image source or an artificial audio source (e.g. - audiotestsrc). - It will become more complicated if we want the element to be a - realtime capture source, such as a video4linux source (for reading - video frames from a TV card) or an ALSA source (for reading data - from soundcards supported by an ALSA-driver). Here, we will need to - make the element aware of timing and clocking. - - - Timestamps can essentially be generated from all the information - given above without any difficulty. We could add a very small amount - of code to generate perfectly timestamped buffers from our - _get ()-function: - - -static void -gst_my_source_init (GstMySource *src) -{ -[..] - src->total_bytes = 0; -} - -static GstData * -gst_my_source_get (GstPad *pad) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - GstBuffer *buf; - GstFormat fmt = GST_FORMAT_TIME; -[..] - GST_BUFFER_DURATION (buf) = GST_BUFFER_SIZE (buf) * (GST_SECOND / (44100 * 2)); - GST_BUFFER_TIMESTAMP (buf) = src->total_bytes * (GST_SECOND / (44100 * 2)); - src->total_bytes += GST_BUFFER_SIZE (buf); - - return GST_DATA (buf); -} - -static GstStateChangeReturn -gst_my_source_change_state (GstElement *element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstMySource *src = GST_MY_SOURCE (element); - - /* First, handle upwards state changes */ - switch (transition) { - case GST_STATE_READY_TO_PAUSED: - /* do something */ - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - /* Now handle downwards state changes after chaining up */ - switch (transition) { - case GST_STATE_PAUSED_TO_READY: - src->total_bytes = 0; - break; - default: - break; - } - - return ret; -} - - - That wasn't too hard. Now, let's assume real-time elements. Those - can either have hardware-timing, in which case we can rely on backends - to provide sync for us (in which case you probably want to provide a - clock), or we will have to emulate that internally (e.g. to acquire - sync in artificial data elements such as - audiotestsrc). - Let's first look at the second option (software sync). The first option - (hardware sync + providing a clock) does not require any special code - with respect to timing, and the clocking section already explained how - to provide a clock. - - -enum { - ARG_0, -[..] - ARG_SYNC, -[..] -}; - -static void -gst_my_source_class_init (GstMySourceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); -[..] - g_object_class_install_property (object_class, ARG_SYNC, - g_param_spec_boolean ("sync", "Sync", "Synchronize to clock", - FALSE, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); -[..] -} - -static void -gst_my_source_init (GstMySource *src) -{ -[..] - src->sync = FALSE; -} - -static GstData * -gst_my_source_get (GstPad *pad) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - GstBuffer *buf; -[..] - if (src->sync) { - /* wait on clock */ - gst_element_wait (GST_ELEMENT (src), GST_BUFFER_TIMESTAMP (buf)); - } - - return GST_DATA (buf); -} - -static void -gst_my_source_get_property (GObject *object, - guint prop_id, - GParamSpec *pspec, - GValue *value) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - - switch (prop_id) { -[..] - case ARG_SYNC: - g_value_set_boolean (value, src->sync); - break; -[..] - } -} - -static void -gst_my_source_get_property (GObject *object, - guint prop_id, - GParamSpec *pspec, - const GValue *value) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - - switch (prop_id) { -[..] - case ARG_SYNC: - src->sync = g_value_get_boolean (value); - break; -[..] - } -} - - - Most of this is GObject wrapping code. The actual code to do - software-sync (in the _get ()-function) - is relatively small. - - - - Using special memory - - In some cases, it might be useful to use specially allocated memory - (e.g. mmap ()'ed DMA'able memory) in - your buffers, and those will require special handling when they are - being dereferenced. For this, &GStreamer; uses the concept of - buffer-free functions. Those are special functions pointers that an - element can set on buffers that it created itself. The given function - will be called when the buffer has been dereferenced, so that the - element can clean up or re-use memory internally rather than using - the default implementation (which simply calls - g_free () on the data pointer). - - -static void -gst_my_source_buffer_free (GstBuffer *buf) -{ - GstMySource *src = GST_MY_SOURCE (GST_BUFFER_PRIVATE (buf)); - - /* do useful things here, like re-queueing the buffer which - * makes it available for DMA again. The default handler will - * not free this buffer because of the GST_BUFFER_DONTFREE - * flag. */ -} - -static GstData * -gst_my_source_get (GstPad *pad) -{ - GstMySource *src = GST_MY_SOURCE (gst_pad_get_parent (pad)); - GstBuffer *buf; -[..] - buf = gst_buffer_new (); - GST_BUFFER_FREE_DATA_FUNC (buf) = gst_my_source_buffer_free; - GST_BUFFER_PRIVATE (buf) = src; - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY | GST_BUFFER_DONTFREE); -[..] - - return GST_DATA (buf); -} - - - Note that this concept should not be used to - decrease the number of calls made to functions such as - g_malloc () inside your element. We - have better ways of doing that elsewhere (&GStreamer; core, Glib, - Glibc, Linux kernel, etc.). - - - diff --git a/docs/pwg/pwg.xml b/docs/pwg/pwg.xml deleted file mode 100644 index 52d729e088..0000000000 --- a/docs/pwg/pwg.xml +++ /dev/null @@ -1,198 +0,0 @@ - - -%image-entities; - -%version-entities; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -GStreamer"> -GStreamer Application Development Manual"> -GStreamer Library Reference"> -]> - - - &TITLEPAGE; - - - - - Introduction - - - &GStreamer; is an extremely powerful and versatile framework for creating - streaming media applications. Many of the virtues of the &GStreamer; - framework come from its modularity: &GStreamer; can seamlessly - incorporate new plugin modules. But because modularity and power often - come at a cost of greater complexity (consider, for example, CORBA), writing new - plugins is not always easy. - - - This guide is intended to help you understand the &GStreamer; framework - (version &GST_VERSION;) so you can develop new plugins to extend the - existing functionality. The guide addresses most issues by following the - development of an example plugin - an audio filter plugin - - written in C. However, the later parts of the guide also present some - issues involved in writing other types of plugins, and the end of the - guide describes some of the Python bindings for &GStreamer;. - - - - &INTRO_PREFACE; - &INTRO_BASICS; - - - - - - Building a Plugin - - - You are now ready to learn how to build a plugin. In this part of the - guide, you will learn how to apply basic &GStreamer; - programming concepts to write a simple plugin. The previous parts of the - guide have contained no explicit example code, perhaps making things a - bit abstract and difficult to understand. In contrast, this section will - present both applications and code by following the development of an - example audio filter plugin called MyFilter. - - - The example filter element will begin with a single input pad and a - single - output pad. The filter will, at first, simply pass media and event data - from its sink pad to its source pad without modification. But by the end - of this part of the guide, you will learn to add some more interesting - functionality, including properties and signal handlers. And after - reading the next part of the guide, , you - will be able to add even more functionality to your plugins. - - - - &BUILDING_BOILER; - &BUILDING_PADS; - &BUILDING_CHAINFN; - &BUILDING_EVENTFN; - &BUILDING_QUERYFN; - &BUILDING_STATE; - &BUILDING_PROPS; - &BUILDING_SIGNALS; - &BUILDING_TESTAPP; - - - - - - Advanced Filter Concepts - - - By now, you should be able to create basic filter elements that can - receive and send data. This is the simple model that &GStreamer; stands - for. But &GStreamer; can do much more than only this! In this chapter, - various advanced topics will be discussed, such as scheduling, special - pad types, clocking, events, interfaces, tagging and more. These topics - are the sugar that makes &GStreamer; so easy to use for applications. - - - - &ADVANCED_REQUEST; - &ADVANCED_SCHEDULING; - &ADVANCED_NEGOTIATION; - &ADVANCED_ALLOCATION; - &ADVANCED_TYPES; - &ADVANCED_EVENTS; - &ADVANCED_CLOCK; - &ADVANCED_QOS; - &ADVANCED_DPARAMS; - &ADVANCED_INTERFACES; - &ADVANCED_TAGGING; - - - - - - - - - Creating special element types - - - By now, we have looked at pretty much any feature that can be embedded - into a &GStreamer; element. Most of this has been fairly low-level and - given deep insights in how &GStreamer; works internally. Fortunately, - &GStreamer; contains some easier-to-use interfaces to create such - elements. In order to do that, we will look closer at the element - types for which &GStreamer; provides base classes (sources, sinks and - transformation elements). We will also look closer at some types of - elements that require no specific coding such as scheduling-interaction - or data passing, but rather require specific pipeline control (e.g. - N-to-1 elements and managers). - - - - &OTHER_BASE; - &OTHER_ONETON; - &OTHER_NTOONE; - &OTHER_MANAGER; - - - - - - Appendices - - - This chapter contains things that don't belong anywhere else. - - - - &APPENDIX_CHECKLIST; - &APPENDIX_PORTING; - &APPENDIX_LICENSING; - &APPENDIX_PYTHON; - - - diff --git a/docs/pwg/titlepage.xml b/docs/pwg/titlepage.xml deleted file mode 100644 index e249d16e86..0000000000 --- a/docs/pwg/titlepage.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - Richard - John - Boulton - - - richard-gst@tartarus.org - - - - - - Erik - Walthinsen - - - omega@temple-baptist.com - - - - - - Steve - Baker - - - stevebaker_org@yahoo.co.uk - - - - - - Leif - Johnson - - - leif@ambient.2y.net - - - - - - Ronald - S. - Bultje - - - rbultje@ronald.bitfreak.net - - - - - - Stefan - Kost - - - ensonic@users.sf.net - - - - - - Tim-Philipp - Müller - - - tim centricular . net - - - - - Wim - Taymans - - - wim.taymans@gmail.com - - - - - - - - This material may be distributed only subject to the terms and - conditions set forth in the Open Publication License, v1.0 or later (the - latest version is presently available at http://www.opencontent.org/openpub/). - - - - &GStreamer; Plugin Writer's Guide (&GST_VERSION;) - - diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 6918f90238..ea563c8641 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -8,7 +8,6 @@ endif always_dirs = \ controller \ helloworld \ - manual \ memory \ netclock \ ptp \ diff --git a/tests/examples/manual/.gitignore b/tests/examples/manual/.gitignore deleted file mode 100644 index 1f16c7d065..0000000000 --- a/tests/examples/manual/.gitignore +++ /dev/null @@ -1,50 +0,0 @@ -Makefile -Makefile.in -*.c -*.o -*.lo -*.la -.deps -.libs - -appsink -appsrc -blockprobe -dynformat -elementget -elementmake -gnome -helloworld -helloworld2 -init -popt -queue -threads -bin -decodebin -dynamic -elementcreate -elementfactory -elementlink -ghostpad -pad -playbin -playsink -norebuffer -probe -query -fakesrc -typefind -effectswitch -testrtpool - -xml-mp3 -xml -xmlTest.gst -README - -*.bb -*.bbg -*.da - -test-registry.* diff --git a/tests/examples/manual/Makefile.am b/tests/examples/manual/Makefile.am deleted file mode 100644 index 42ae9e5911..0000000000 --- a/tests/examples/manual/Makefile.am +++ /dev/null @@ -1,136 +0,0 @@ -# if HAVE_LIBGNOMEUI -# GNOME = gnome -# else -GNOME = -# endif - -# gnome_LDADD = $(GST_OBJ_LIBS) $(LIBGNOMEUI_LIBS) -# gnome_CFLAGS = $(GST_OBJ_CFLAGS) $(LIBGNOMEUI_CFLAGS) - -CHECK_REGISTRY = $(top_builddir)/tests/examples/manual/test-registry.reg - -REGISTRY_ENVIRONMENT = \ - GST_REGISTRY=$(CHECK_REGISTRY) - -AM_TESTS_ENVIRONMENT = \ - $(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 - -EXTRA_DIST = extract.pl - -EXAMPLES = \ - $(GNOME) \ - elementcreate \ - elementmake \ - elementfactory \ - elementget \ - elementlink \ - bin \ - pad \ - ghostpad \ - helloworld \ - init \ - query \ - typefind \ - blockprobe \ - probe \ - appsrc \ - appsink \ - dynformat \ - effectswitch \ - norebuffer \ - playbin \ - decodebin \ - playsink - -BUILT_SOURCES = \ - elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c \ - bin.c \ - pad.c ghostpad.c \ - gnome.c \ - helloworld.c \ - init.c \ - query.c \ - typefind.c \ - blockprobe.c \ - probe.c \ - appsrc.c \ - appsink.c \ - dynformat.c \ - effectswitch.c \ - norebuffer.c \ - playbin.c decodebin.c \ - playsink.c - -if HAVE_PTHREAD -BUILT_SOURCES += testrtpool.c -EXAMPLES += testrtpool -endif - -CLEANFILES = core core.* test-registry.* *.gcno *.gcda $(BUILT_SOURCES) - -AM_CFLAGS = $(GST_OBJ_CFLAGS) -LDADD = $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ - $(GST_OBJ_LIBS) - -elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c: $(top_srcdir)/docs/manual/basics-elements.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -bin.c : $(top_srcdir)/docs/manual/basics-bins.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -pad.c ghostpad.c: $(top_srcdir)/docs/manual/basics-pads.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -gnome.c: $(top_srcdir)/docs/manual/appendix-integration.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -helloworld.c: $(top_srcdir)/docs/manual/basics-helloworld.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -init.c: $(top_srcdir)/docs/manual/basics-init.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -query.c: $(top_srcdir)/docs/manual/advanced-position.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -typefind.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -blockprobe.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -probe.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -appsrc.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -appsink.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -dynformat.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -effectswitch.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -norebuffer.c: $(top_srcdir)/docs/manual/advanced-buffering.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -playbin.c decodebin.c playsink.c: $(top_srcdir)/docs/manual/highlevel-playback.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -testrtpool.c: $(top_srcdir)/docs/manual/advanced-threads.xml - $(PERL_PATH) $(srcdir)/extract.pl $@ $< - -TESTS = bin \ - elementcreate elementfactory elementget elementlink elementmake \ - ghostpad init - -noinst_PROGRAMS = $(EXAMPLES) - -testrtpool_LDADD = $(GST_OBJ_LIBS) $(PTHREAD_LIBS) -testrtpool_CFLAGS = $(GST_OBJ_CFLAGS) $(PTHREAD_CFLAGS) diff --git a/tests/examples/manual/extract.pl b/tests/examples/manual/extract.pl deleted file mode 100755 index a4b7c1c9a1..0000000000 --- a/tests/examples/manual/extract.pl +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/perl - -# extract code fragments from xml program listings -# first argument: source code file to find -# second argument: xml files to extract code from - -# main - -# decodes xml by translating & < > back to what they should be -# and also ignore -# and -sub -xml_decode ($) -{ - my $input = shift; - - $input =~ s/\&/&/g; - $input =~ s/<//g; - - if ($input =~ //) { $input = ""; } - if ($input =~ //) { $input = ""; } - - #print "Returning line $input"; - return $input; -} - -# main -my $output = shift @ARGV; -my $outputname; - -# strip path parts -if ($output =~ m/.*\/(.*)$/) -{ - $outputname = $1; -} -else -{ - $outputname = $output; -} - -$found = 0; -%blocks = (); - -foreach $file (@ARGV) -{ - open FILE, $file or die "Cannot open file $file"; - - while ($line = ) - { - if ($line =~ //) - { - $found = 1; - $block_id = $1; - $block = "\n/*** block $block_id from $file ***/\n"; - - print "Extracting $outputname block $block_id from $file\n"; - - while ($line = ) - { - if ($line =~ //) - { - last; - } - $block .= xml_decode ($line); - } - $blocks{$block_id} = $block; - } - } -} - - -if (!$found) -{ - print "Could not find $outputname example !\n"; - exit(1); -} - -# now output all the blocks in the right order -open OUTPUT, ">$output"; -@block_ids = keys %blocks; -foreach $block_id (sort @block_ids) -{ - print "Writing $output block $block_id\n"; - print OUTPUT $blocks{$block_id}; -} -close OUTPUT;