diff --git a/docs/Makefile.am b/docs/Makefile.am index 46b3674ea3..666d62ef69 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -5,8 +5,8 @@ else SUBDIRS_PLUGINS = endif -SUBDIRS = manual fwg gst libs $(SUBDIRS_PLUGINS) devhelp -DIST_SUBDIRS = manual fwg gst libs plugins xsl devhelp +SUBDIRS = manual pwg gst libs $(SUBDIRS_PLUGINS) devhelp +DIST_SUBDIRS = manual pwg gst libs plugins xsl devhelp EXTRA_DIST = slides manuals.mak diff --git a/docs/pwg/.gitignore b/docs/pwg/.gitignore new file mode 100644 index 0000000000..c9012a5e02 --- /dev/null +++ b/docs/pwg/.gitignore @@ -0,0 +1,13 @@ +Makefile +Makefile.in +*.bak +.deps +images +gst-plugin-writers-guide +gst-plugin-writers-guide.pdf +gst-plugin-writers-guide.ps +gst-plugin-writers-guide.dvi +gst-plugin-writers-guide.tex +gst-plugin-writers-guide.log +gst-plugin-writers-guide.aux +gst-plugin-writers-guide.junk diff --git a/docs/pwg/Makefile.am b/docs/pwg/Makefile.am new file mode 100644 index 0000000000..72a07dc4c5 --- /dev/null +++ b/docs/pwg/Makefile.am @@ -0,0 +1,18 @@ +DOC=gst-plugin-writers-guide +MAIN=$(DOC).xml +XML=$(wildcard *.xml) +XSLFO=$(srcdir)/../xsl/fo.xsl +XSLFOMODS=$(srcdir)/../xsl/ulink.xsl $(srcdir)/../xsl/keycombo.xsl +XSLHTML=$(srcdir)/../xsl/html.xsl +XSLHTMLMODS=$(srcdir)/../xsl/fileext.xsl $(srcdir)/../xsl/admon.xsl \ + $(srcdir)/../xsl/keycombo.xsl $(srcdir)/../xsl/css.xsl +XSLS=$(XSLFO) $(XSLFOMODS) $(XSLHTML) $(XSLHTMLMODS) +FIGS= # $(wildcard *.fig) (uncomment when pngs are added) +PNGS=$(FIGS:.fig=.png) +PDFS=$(FIGS:.fig=.pdf) +SRC=$(XML) +CSS=base.css + +EXTRA_DIST = $(XML) $(FIGS) $(CSS) magic-png magic-pdf + +include $(srcdir)/../manuals.mak diff --git a/docs/pwg/advanced-clock.xml b/docs/pwg/advanced-clock.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/pwg/advanced-dparams.xml b/docs/pwg/advanced-dparams.xml new file mode 100644 index 0000000000..2311380d50 --- /dev/null +++ b/docs/pwg/advanced-dparams.xml @@ -0,0 +1,481 @@ + + + + + Supporting Dynamic Parameters + + 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 expose these parameters as Dynamic Parameters which can be + manipulated by any Dynamic Parameters aware application. + + + Throughout this section, the term dparams will be used + as an abbreviation for "Dynamic Parameters". + + + + Comparing Dynamic Parameters with GObject Properties + + Your first exposure to dparams may be to convert an existing element from + using object properties to using dparams. The following table gives an + overview of the difference between these approaches. The significance of + these differences should become apparent later on. + + + + + + + Object Properties + Dynamic Parameters + + + + + Parameter definition + Class level at compile time + Any level at run time + + + Getting and setting + Implemented by element subclass as functions + Handled entirely by dparams subsystem + + + Extra objects required + None - all functionality is derived from base GObject + Element needs to create and store a GstDParamManager at object creation + + + Frequency and resolution of updates + Object properties will only be updated between calls to _get, _chain or _loop + dparams can be updated at any rate independant of calls to _get, _chain or _loop up to sample-level accuracy + + + + + + + + + Getting Started + + + The dparams subsystem is contained within the + gstcontrol library. You need to include the header in + your element's source file: + + + #include <gst/control/control.h> + + + + Even though the gstcontrol library may be linked into + the host application, you should make sure it is loaded in your + plugin_init function: + + + static gboolean + plugin_init (GModule *module, GstPlugin *plugin) + { + ... + + /* load dparam support library */ + if (!gst_library_load ("gstcontrol")) + { + gst_info ("example: could not load support library: 'gstcontrol'\n"); + return FALSE; + } + + ... + } + + + + You need to store an instance of GstDParamManager in + your element's struct: + + + struct _GstExample { + GstElement element; + ... + + GstDParamManager *dpman; + + ... + }; + + + + The GstDParamManager can be initialised in your + element's init function: + + + static void + gst_example_init (GstExample *example) + { + ... + + example->dpman = gst_dpman_new ("example_dpman", GST_ELEMENT(example)); + + ... + } + + + + + + Defining Parameter Specificiations + + You can define the dparams you need anywhere within your element but will + usually need to do so in only a couple of places: + + + In the element init function, just after the call + to gst_dpman_new + + + Whenever a new pad is created so that parameters can affect data going + into or out of a specific pad. An example of this would be a mixer + element where a seperate volume parameter is needed on every pad. + + + + + There are three different ways the dparams subsystem can pass parameters + into your element. Which one you use will depend on how that parameter is + used within your element. Each of these methods has its own function to + define a required dparam: + + gst_dpman_add_required_dparam_direct + gst_dpman_add_required_dparam_callback + gst_dpman_add_required_dparam_array + + These functions will return TRUE if the required dparam was added + successfully. + + + The following function will be used as an example. + + gboolean + gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, + GParamSpec *param_spec, + gboolean is_log, + gboolean is_rate, + gpointer update_data) + + The common parameters to these functions are: + + + GstDParamManager *dpman the element's dparam + manager + + + GParamSpec *param_spec the param spec which defines + the required dparam + + + gboolean is_log whether this dparam value should be + interpreted on a log scale (such as a frequency or a decibel value) + + + gboolean is_rate whether this dparam value is a + proportion of the sample rate. For example with a sample rate of 44100, + 0.5 would be 22050 Hz and 0.25 would be 11025 Hz. + + + + + Direct Method + + This method is the simplest and has the lowest overhead for parameters + which change less frequently than the sample rate. First you need + somewhere to store the parameter - this will usually be in your element's + stuct. + + + struct _GstExample { + GstElement element; + ... + + GstDParamManager *dpman; + gfloat volume; + ... + }; + + + Then to define the required dparam just call + gst_dpman_add_required_dparam_direct and pass in the + location of the parameter to change. In this case the location is + &(example->volume). + + + gst_dpman_add_required_dparam_direct ( + example->dpman, + g_param_spec_float("volume","Volume","Volume of the audio", + 0.0, 1.0, 0.8, G_PARAM_READWRITE), + FALSE, + FALSE, + &(example->volume) + ); + + + You can now use example->volume anywhere in your + element knowing that it will always contain the correct value to use. + + + + Callback Method + + This should be used if the you have other values to calculate whenever a + parameter changes. If you used the direct method you wouldn't know if a + parameter had changed so you would have to recalculate the other values + every time you needed them. By using the callback method, other values + only have to be recalculated when the dparam value actually changes. + + + The following code illustrates an instance where you might want to use the + callback method. If you had a volume dparam which was represented by a + gfloat number, your element may only deal with integer arithmatic. The + callback could be used to calculate the integer scaler when the volume + changes. First you will need somewhere to store these values. + + + struct _GstExample { + GstElement element; + ... + + GstDParamManager *dpman; + gfloat volume_f; + gint volume_i; + ... + }; + + + When the required dparam is defined, the callback function + gst_example_update_volume and some user data (which + in this case is our element instance) is passed in to the call to + gst_dpman_add_required_dparam_callback. + + + gst_dpman_add_required_dparam_callback ( + example->dpman, + g_param_spec_float("volume","Volume","Volume of the audio", + 0.0, 1.0, 0.8, G_PARAM_READWRITE), + FALSE, + FALSE, + gst_example_update_volume, + example + ); + + + The callback function needs to conform to this signiture + + +typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data); + + + In our example the callback function looks like this + + +static void +gst_example_update_volume(GValue *value, gpointer data) +{ + GstExample *example = (GstExample*)data; + g_return_if_fail(GST_IS_EXAMPLE(example)); + + example->volume_f = g_value_get_float(value); + example->volume_i = example->volume_f * 8192; +} + + + Now example->volume_i can be used elsewhere and it + will always contain the correct value. + + + + Array Method + + This method is quite different from the other two. It could be thought of + as a specialised method which should only be used if you need the + advantages that it provides. Instead of giving the element a single value + it provides an array of values where each item in the array corresponds to + a sample of audio in your buffer. There are a couple of reasons why this + might be useful. + + + + + Certain optimisations may be possible since you can iterate over your + dparams array and your buffer data together. + + + Some dparams may be able to interpolate changing values at the sample + rate. This would allow the array to contain very smoothly changing + values which may be required for the stability and quality of some DSP + algorithms. + + + + The array method is currently the least mature of the three methods and is + not yet ready to be used in elements, but plugin writers should be aware + of its existance for the future. + + + + + + The Data Processing Loop + + This is the most critical aspect of the dparams subsystem as it relates to + elements. In a traditional audio processing loop, a for + loop will usually iterate over each sample in the buffer, processing one + sample at a time until the buffer is finished. A simplified loop with no + error checking might look something like this. + + +static void +example_chain (GstPad *pad, GstBuffer *buf) +{ + ... + gfloat *float_data; + int j; + GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad)); + int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat); + float_data = (gfloat *)GST_BUFFER_DATA(buf); + ... + for (j = 0; j < num_samples; j++) { + float_data[j] *= example->volume; + } + ... +} + + + To make this dparams aware, a couple of changes are needed. + + +static void +example_chain (GstPad *pad, GstBuffer *buf) +{ + ... + int j = 0; + GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad)); + int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat); + gfloat *float_data = (gfloat *)GST_BUFFER_DATA(buf); + int frame_countdown = GST_DPMAN_PREPROCESS(example->dpman, num_samples, GST_BUFFER_TIMESTAMP(buf)); + ... + while (GST_DPMAN_PROCESS_COUNTDOWN(example->dpman, frame_countdown, j)) { + float_data[j++] *= example->volume; + } + ... +} + + + The biggest changes here are 2 new macros, + GST_DPMAN_PREPROCESS and + GST_DPMAN_PROCESS_COUNTDOWN. You will also notice that + the for loop has become a while loop. + GST_DPMAN_PROCESS_COUNTDOWN is called as the condition + for the while loop so that any required dparams can be updated in the middle + of a buffer if required. This is because one of the required behaviours of + dparams is that they can be sample accurate. This means + that parameters change at the exact timestamp that they are supposed to - + not after the buffer has finished being processed. + + + It may be alarming to see a macro as the condition for a while loop, but it + is actually very efficient. The macro expands to the following. + + +#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \ + (frame_countdown-- || \ + (frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count))) + + + So as long as frame_countdown is greater than 0, + GST_DPMAN_PROCESS will not be called at all. Also in + many cases, GST_DPMAN_PROCESS will do nothing and + simply return 0, meaning that there is no more data in the buffer to + process. + + + The macro GST_DPMAN_PREPROCESS will do the following: + + + Update any dparams which are due to be updated. + + + Calculate how many samples should be processed before the next required + update + + + Return the number of samples until next update, or the number of samples + in the buffer - whichever is less. + + + In fact GST_DPMAN_PROCESS may do the same things as + GST_DPMAN_PREPROCESS depending on the mode that the + dparam manager is running in (see below). + + + DParam Manager Modes + + A brief explanation of dparam manager modes might be useful here even + though it doesn't generally affect the way your element is written. There + are different ways media applications will be used which require that an + element's parameters be updated in differently. These include: + + + Timelined - all parameter changes are known in + advance before the pipeline is run. + + + Realtime low-latency - Nothing is known ahead of + time about when a parameter might change. Changes need to be + propagated to the element as soon as possible. + + + When a dparam-aware application gets the dparam manager for an element, + the first thing it will do is set the dparam manager mode. Current modes + are "synchronous" and + "asynchronous". + + + If you are in a realtime low-latency situation then the + "synchronous" mode is appropriate. During + GST_DPMAN_PREPROCESS this mode will poll all dparams + for required updates and propagate them. + GST_DPMAN_PROCESS will do nothing in this mode. To + then achieve the desired latency, the size of the buffers needs to be + reduced so that the dparams will be polled for updates at the desired + frequency. + + + In a timelined situation, the "asynchronous" mode + will be required. This mode hasn't actually been implemented yet but will + be described anyway. The GST_DPMAN_PREPROCESS call + will precalculate when and how often each dparam needs to update for the + duration of the current buffer. From then on + GST_DPMAN_PROCESS will propagate the calculated + updates each time it is called until end of the buffer. If the application + is rendering to disk in non-realtime, the render could be sped up by + increasing the buffer size. In the "asynchronous" + mode this could be done without affecting the sample accuracy of the + parameter updates + + + + DParam Manager Modes + + All of the explanation so far has presumed that the buffer contains audio + data with many samples. Video should be regarded differently since a video + buffer often contains only 1 frame. In this case some of the complexity of + dparams isn't required but the other benefits still make it useful for + video parameters. If a buffer only contains one frame of video, only a + single call to GST_DPMAN_PREPROCESS should be + required. For more than one frame per buffer, treat it the same as the + audio case. + + + diff --git a/docs/pwg/advanced-midi.xml b/docs/pwg/advanced-midi.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/pwg/advanced-request.xml b/docs/pwg/advanced-request.xml new file mode 100644 index 0000000000..01f8afcd78 --- /dev/null +++ b/docs/pwg/advanced-request.xml @@ -0,0 +1,6 @@ + + Request pads + + aka pushing and pulling + + diff --git a/docs/pwg/advanced-scheduling.xml b/docs/pwg/advanced-scheduling.xml new file mode 100644 index 0000000000..249f9ff9ad --- /dev/null +++ b/docs/pwg/advanced-scheduling.xml @@ -0,0 +1,27 @@ + + How scheduling works + + aka pushing and pulling + + + + + How a loopfunc works + + aka pulling and pushing + + + + + Adding a second output + + Identity is now a tee + + + + + Modifying the test application + + + + diff --git a/docs/pwg/advanced-types.xml b/docs/pwg/advanced-types.xml new file mode 100644 index 0000000000..62ed2cf1aa --- /dev/null +++ b/docs/pwg/advanced-types.xml @@ -0,0 +1,88 @@ + + + + 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 neccessary 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, the &GStreamer; + wiki. + + + + + 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 + + + + + + + + A Simple Mime Type + + + + + + + + Type Properties + + + + + + + + Typefind Functions and Autoplugging + + + + diff --git a/docs/pwg/appendix-checklist.xml b/docs/pwg/appendix-checklist.xml new file mode 100644 index 0000000000..d67fcb7864 --- /dev/null +++ b/docs/pwg/appendix-checklist.xml @@ -0,0 +1,14 @@ + + + Things to check when writing a filter + + + + + + + Things to check when writing a source or sink + + + + diff --git a/docs/pwg/appendix-python.xml b/docs/pwg/appendix-python.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/pwg/base.css b/docs/pwg/base.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/pwg/basics-autoplugging.xml b/docs/pwg/basics-autoplugging.xml new file mode 100644 index 0000000000..f6a927d717 --- /dev/null +++ b/docs/pwg/basics-autoplugging.xml @@ -0,0 +1,18 @@ + + + + + Autopluggers + + &GStreamer; has an autoplugging mechanism, which enables application writers + to simply specify start and end elements for a path, and the system will + then create a path which links these elements, in accordance with the type + information provided by the elements. + + + It is possible to devise many different schemes for generating such + pathways, perhaps to optimise based on special criteria, or with some + specific constraints. It is thus possible to define new autoplugging + systems, using the plugin system. + + diff --git a/docs/pwg/basics-buffers.xml b/docs/pwg/basics-buffers.xml new file mode 100644 index 0000000000..28267d4d29 --- /dev/null +++ b/docs/pwg/basics-buffers.xml @@ -0,0 +1,32 @@ + + + + + Buffers + + Buffers are structures used to pass data between elements. All streams of + data are chopped up into chunks which are stored in buffers. Buffers can be + of any size, and also contain metadata indicating the type of data contained + in them. Buffers can be allocated by various different schemes, and may + either be passed on by elements or unreferenced (and the memory used by the + buffer freed). + + + + Anatomy of a buffer + + + + + + Refcounts and mutability + + + + + + Metadata + + + + diff --git a/docs/pwg/basics-elements.xml b/docs/pwg/basics-elements.xml new file mode 100644 index 0000000000..1caf8d1beb --- /dev/null +++ b/docs/pwg/basics-elements.xml @@ -0,0 +1,39 @@ + + + + + Elements, Plugins, and Filters + + In the &GStreamer; framework, a plugin is a specific + sort of code module that gets loaded when a program requests the + functionality that the plugin provides. A plugin is essentially a shared + code library. +Filters are an + important subset of plugins that process data, as opposed to producing or + consuming data. (Producers and consumers of data are called + source and sink plugins, + respectively.) + + + Elements are at the core of &GStreamer;. Without elements, &GStreamer; is + just a bunch of pipe fittings with nothing to connect. A large number of + elements (filters, sources, and sinks) ship with &GStreamer;, but extra + elements can also be written. The purpose of this guide is to help you + learn to create new elements. + + + An element may be constructed in several different ways, but all must + conform to the same basic rules. This guide presents one basic way to build + a filter elementA simple filter may be built with the + FilterFactory, where the only code that need be written is the actual filter + code. A more complex filter, or a source or sink, will need to be written + out fully for complete access to the features and performance possible with + &GStreamer;. + + + The implementation of a new element will be contained in a plugin: a single + plugin may contain the implementation of several elements, or just a single + one. + + + diff --git a/docs/pwg/basics-events.xml b/docs/pwg/basics-events.xml new file mode 100644 index 0000000000..ac84310d02 --- /dev/null +++ b/docs/pwg/basics-events.xml @@ -0,0 +1,8 @@ + + + + + Events + + + diff --git a/docs/pwg/basics-plugins.xml b/docs/pwg/basics-plugins.xml new file mode 100644 index 0000000000..051f99bf3c --- /dev/null +++ b/docs/pwg/basics-plugins.xml @@ -0,0 +1,30 @@ + + + + + Plugins + + Extensions to &GStreamer; can be made using a plugin mechanism. This is used + extensively in &GStreamer; even if only the standard package is being used: + a few very basic functions reside in the core library, and all others are + implemented in plugins. + + + Plugins are only loaded when needed: a plugin registry is used to store the + details of the plugins so that it is not neccessary to load all plugins to + determine which are needed. This registry needs to be updated whenever a new + plugin is added to the system: see the gst-register + utility and the documentation in the &GstAppDevMan; for more details. + + + User extensions to &GStreamer; can be installed in the main plugin + directory, and will immediately be available for use in applications. + gst-register should be run to update the repository: + but the system should work correctly even if it hasn't been - it will just + take longer to load the correct plugin. + + + User specific plugin directories and registries will be available in future + versions of &GStreamer;. + + diff --git a/docs/pwg/basics-types.xml b/docs/pwg/basics-types.xml new file mode 100644 index 0000000000..e0e130a596 --- /dev/null +++ b/docs/pwg/basics-types.xml @@ -0,0 +1,15 @@ + + + + + Typing and Properties + + A type system is used to ensure that the data passed between elements is in + a recognised format, and that the various parameters required to fully + specify that format match up correctly. Each connection that is made between + elements has a specified type. This is related, but different, to the + metadata in buffers which describes the type of data in that particular + buffer. See the next chapter of this document for details of the available + types. + + diff --git a/docs/pwg/building-boiler.xml b/docs/pwg/building-boiler.xml new file mode 100644 index 0000000000..5e864fd6af --- /dev/null +++ b/docs/pwg/building-boiler.xml @@ -0,0 +1,295 @@ + + + + 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 simple + command line tools to copy and modify a template plugin and thus create your + new plugin. By the end of all this, you will have a functional audio filter + plugin that you can compile and test. + + + + + + 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. + + + The first step is to check out a copy of the + gst-template CVS module to get an important tool and + the source code template for the basic &GStreamer; plugin. To check out + the gst-template module, type the following two + commands on a command line: + + +shell $ cvs -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer login +Logging in to :pserver:anonymous@cvs.gstreamer.sourceforge.net:2401/cvsroot/gstreamer +CVS password: +shell $ cvs -z3 -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer co gst-template +U gst-template/README +U gst-template/gst-app/AUTHORS +U gst-template/gst-app/ChangeLog +U gst-template/gst-app/Makefile.am +U gst-template/gst-app/NEWS +U gst-template/gst-app/README +U gst-template/gst-app/autogen.sh +U gst-template/gst-app/configure.ac +U gst-template/gst-app/src/Makefile.am +... + + + After the first command, you will have to press ENTER to + log in to the CVS server. You might have to log in twice. The second + command will check out a series of files and directories into ./gst-template. The template you will be + using is in ./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. + + + + + + + Using Filterstamp + + 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 script called + pluginstamp.sh in the tools/ directory of the + gst-template source tree that does exactly this. + + + To use pluginstamp.sh, first open up a terminal window. + Change to the gst-template + directory, and then run the pluginstamp.sh command. The + arguments to the pluginstamp.sh are: + + + + the name of the plugin, and + + + + the directory that should hold a new subdirectory for the source tree + of the plugin. + + + + + Note that capitalization is important for the name of the plugin. Under + some operating systems, capitalization is also important when specifying + directory names. For example, the + following commands create the ExampleFilter plugin based on the plugin + template and put the output files in a new directory called ~/src/examplefilter/: + + +shell $ cd gst-template +shell $ tools/pluginstamp.sh ExampleFilter ~/src + + + + + + + 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 + pluging system, and doesn't depend on reading a header file, this is not + crucial.) + + The code here can be found in + examples/pwg/examplefilter/boiler/gstexamplefilter.h. + + + + Example Plugin Header File + + /* Definition of structure storing data for this element. */ + typedef struct _GstExample GstExample; + + struct _GstExample { + GstElement element; + + GstPad *sinkpad,*srcpad; + + gint8 active; + }; + + /* Standard definition defining a class for this element. */ + typedef struct _GstExampleClass GstExampleClass; + struct _GstExampleClass { + GstElementClass parent_class; + }; + + /* Standard macros for defining types for this element. */ + #define GST_TYPE_EXAMPLE \ + (gst_example_get_type()) + #define GST_EXAMPLE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_EXAMPLE,GstExample)) + #define GST_EXAMPLE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_EXAMPLE,GstExample)) + #define GST_IS_EXAMPLE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_EXAMPLE)) + #define GST_IS_EXAMPLE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EXAMPLE)) + + /* Standard function returning type information. */ + GtkType gst_example_get_type(void); + + + + + + + + Creating a Filter With FilterFactory (Future) + + A plan for the future is to create a FilterFactory, to make the process of + making a new filter a simple process of specifying a few details, and + writing a small amount of code to perform the actual data processing. + Ideally, a FilterFactory would perform the tasks of boilerplate creation, + code functionality implementation, and filter registration. + + + Unfortunately, this has not yet been implemented. Even when someone + eventually does write a FilterFactory, this element will not be able to + cover all the possibilities available for filter writing. Thus, some + plugins will always need to be manually coded and registered. + + + Here is a rough outline of what is planned: You run the FilterFactory and + give the factory a list of appropriate function pointers and data + structures to define a filter. With a reasonable measure of preprocessor + magic, you just need to provide a name for the filter and definitions of + the functions and data structures desired. Then you call a macro from + within plugin_init() that registers the new filter. All the fluff that + goes into the definition of a filter is thus be hidden from view. + + + + + + + GstElementDetails + + The GstElementDetails structure gives a heirarchical type for the element, + a human-readable description of the element, as well as author and version + data. The entries are: + + + + A long, english, name for the element. + + The type of the element, as a heirarchy. The heirarchy is defined by + specifying the top level category, followed by a "/", followed by the + next level category, etc. The type should be defined according to the + guidelines elsewhere in this document. (FIXME: write the guidelines, and + give a better reference to them) + + A brief description of the purpose of the element. + + The version number of the element. For elements in the main GStreamer + source code, this will often simply be VERSION, which is a macro defined + to be the version number of the current GStreamer version. The only + requirement, however, is that the version number should increase + monotonically. + + + Version numbers should be stored in major.minor.patch form: ie, 3 + (decimal) numbers, separated by periods (.). + + The name of the author of the element, optionally followed by a contact + email address in angle brackets. + + The copyright details for the element. + + + + For example: + + + static GstElementDetails example_details = { + "An example plugin", + "Example/FirstExample", + "Shows the basic structure of a plugin", + VERSION, + "your name <your.name@your.isp>", + "(C) 2001", + }; + + + + + + + Constructor Functions + + Each element has two functions which are used for construction of an + element. These are the _class_init() function, which is used to initialise + the class (specifying what signals and arguments the class has and setting + up global state), and the _init() function, which is used to initialise a + specific instance of the class. + + + + + + + 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 must return a pointer to a newly + allocated GstPlugin structure. This structure contains the details of all + the facilities provided by the plugin, and is the mechanism by which the + definitions are made available to the rest of the &GStreamer; system. Helper + functions are provided to help fill the structure: for future compatability + it is recommended that these functions are used, as documented below, rather + than attempting to access the structure directly. + + + 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 new file mode 100644 index 0000000000..11fb3b2076 --- /dev/null +++ b/docs/pwg/building-chainfn.xml @@ -0,0 +1,8 @@ + + + + + The chain function + + + diff --git a/docs/pwg/building-pads.xml b/docs/pwg/building-pads.xml new file mode 100644 index 0000000000..f327af13ea --- /dev/null +++ b/docs/pwg/building-pads.xml @@ -0,0 +1,9 @@ + + + + + Specifying the pads + + + + diff --git a/docs/pwg/building-props.xml b/docs/pwg/building-props.xml new file mode 100644 index 0000000000..16d4b204c1 --- /dev/null +++ b/docs/pwg/building-props.xml @@ -0,0 +1,9 @@ + + + + Adding Arguments + + Define arguments in enum. + + + diff --git a/docs/pwg/building-signals.xml b/docs/pwg/building-signals.xml new file mode 100644 index 0000000000..82991047be --- /dev/null +++ b/docs/pwg/building-signals.xml @@ -0,0 +1,9 @@ + + + + + Signals + + Define signals in enum. + + diff --git a/docs/pwg/building-state.xml b/docs/pwg/building-state.xml new file mode 100644 index 0000000000..4d8a1e1474 --- /dev/null +++ b/docs/pwg/building-state.xml @@ -0,0 +1,14 @@ + + + What are states? + + + + + + + Mangaging filter state + + + + diff --git a/docs/pwg/building-testapp.xml b/docs/pwg/building-testapp.xml new file mode 100644 index 0000000000..bfbd66abdd --- /dev/null +++ b/docs/pwg/building-testapp.xml @@ -0,0 +1,25 @@ + + Initialization + + + + + + Instantiating the plugins + + (NOTE: we really should have a debugging Sink) + + + + + Connecting the plugins + + + + + + Running the pipeline + + + + diff --git a/docs/pwg/gst-plugin-writers-guide.xml b/docs/pwg/gst-plugin-writers-guide.xml new file mode 100644 index 0000000000..dfee7db9fb --- /dev/null +++ b/docs/pwg/gst-plugin-writers-guide.xml @@ -0,0 +1,156 @@ + + +%magic-entities; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GStreamer"> + +GStreamer Application Development Manual"> +GStreamer Library Reference"> +]> + + + &TITLEPAGE; + + + + + Introduction + + + &GStreamer; is an exremely 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 + so you can develop new plugins to extend &GStreamer;'s functionality. + This guide introduces most of the basic plugin writing issues in version + &GstVersion; of &GStreamer;. This guide presents most issues in the + context of an example audio filter plugin written in C. However, the + guide also addresses some issues involved in writing other types of + plugins, and the end of the guide also describes some of the Python + bindings for &GStreamer;. + + + + &INTRO_PREFACE; + &INTRO_BASICS; + + + + + + Building a Filter + + + You now have the neccessary concepts to build your first plugin. In this + part of the guide, you will learn how to apply these concepts to write a + simple audio filter 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 ExampleFilter. + + + The example filter will begin with a single input pad and a single + output pad. The filter will, at first, simply pass data through 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. + + + The example code used in this part of the guide can be found in + examples/pwg/examplefilter/ in + your &GStreamer; directory. + + + + &BUILDING_BOILER; + &BUILDING_PADS; + &BUILDING_CHAINFN; + &BUILDING_STATE; + &BUILDING_PROPS; + &BUILDING_SIGNALS; + &BUILDING_TESTAPP; + + + + + + Advanced Filter Concepts + + + + + + &ADVANCED_SCHEDULING; + &ADVANCED_TYPES; + &ADVANCED_REQUEST; + &ADVANCED_CLOCK; + &ADVANCED_DPARAMS; + &ADVANCED_MIDI; + + + + + + Other Element Types + + + + + + &OTHER_SOURCE; + &OTHER_SINK; + &OTHER_AUTOPLUGGER; + + + + + + Appendices + + + + + + &APPENDIX_CHECKLIST; + &APPENDIX_PYTHON; + + + diff --git a/docs/pwg/intro-basics.xml b/docs/pwg/intro-basics.xml new file mode 100644 index 0000000000..31770d4ab4 --- /dev/null +++ b/docs/pwg/intro-basics.xml @@ -0,0 +1,472 @@ + + + + Basic Concepts + + This chapter of the guide introduces the basic concepts of &GStreamer;. + Understanding these concepts will help you see 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. An element provides some sort of + functionality when connected with other elements. Without elements, + &GStreamer; is just a bunch of conceptual pipe fittings with nothing to + connect. A large number of elements ship with &GStreamer;, but extra + elements can also be written. The purpose of this guide is to help you + learn to create new elements, which are encapsulated in plugins as + described below. + + + A filter is an important type of element that + processes a stream of data, as opposed to producing or consuming streams + of data. Producers and consumers of data are called + source and sink elements, + respectively. + + + 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 a shared object file or 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 filter type element. + + + The plugin mechanism is used everywhere in &GStreamer;, even if only the + standard package is 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 XML 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 connections and data flow + between elements in &GStreamer;. A pad can be viewed as a + place on an element where connections may be made with + other elements. Pads have specific data handling capabilities: That is, a + pad only knows how to give or receive certain types of data. Connections + are only allowed when the capabilities of 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 television. Connecting the DVD player + to the amplifier is allowed only because both devices have audio jacks, + and connecting the television to the DVD player is allowed because both + devices have compatible video jacks. Pads in &GStreamer; serve the same + purpose as the jacks in the home theater system. + + + See the &GstLibRef; for the current implementation details of a GstPad. + + + + + + + Buffers + + 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. + Buffers are structures used to hold these chunks of + data. Buffers can be of any size, theoretically. Buffers may contain any + sort of data that the two pads involved 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: + + + + A pointer to the buffer's data. + + + + + An integer indicating the size of the buffer's data. + + + + + A GstData object describing the type of the + buffer's data. + + + + + A reference count indicating the number of elements currently + holding a reference to the buffer. When the buffer reference count + falls to zero, the buffer will be unlinked, and its memory will be + freed in some sense (see the next part about for more details). + + + + + + See the &GstLibRef; for the current implementation details of a GstBuffer. + + + + Buffer Allocation and Buffer Pools + + Buffers can be allocated using various schemes, and they may either be + passed on by an element or unreferenced, thus freeing the memory used by + the buffer. + + + Normally, filter elements in &GStreamer; deal with a buffer in place, + meaning that they do not create or destroy buffers. Sometimes, however, + elements might need to alter the reference count of a buffer to copy or + destroy the buffer, or to create a new buffer. For the most part, this + guide does not deal with elements that alter a buffer's reference count, + but buffer referencing is an important concept to know. + + + + + + + + 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 connecting pads between elements. Each connection that is + made between elements has a specified type. + + + + + + The Basic Types + + &GStreamer; already supports many basic media types. Following is a + table of the basic types used for buffers in &GStreamer;. The table + contains the name ("mime type") and a description of the type, the + properties associated with the type, and the meaning of each property. + + + + Table of Basic Types + + + + + Mime Type + Description + Property + Property Type + Property Values + Property Description + + + + + + + + + audio/raw + + Unstructured and uncompressed raw audio data. + + rate + integer + greater than 0 + + The sample rate of the data, in samples per second. + + + + channels + integer + greater than 0 + + The number of channels of audio data. + + + + format + string + int or float + + The format in which the audio data is passed. + + + + law + integer + 0, 1, or 2 + + (Valid only if the data is in integer format.) The law used to + describe the data. The value 0 indicates linear, 1 + indicates mu law, and 2 indicates + A law. + + + + endianness + boolean + 0 or 1 + + (Valid only if the data is in integer format.) The order of bytes + in a sample. The value 0 means little-endian (bytes + are least significant first). The value 1 means + big-endian (most significant byte first). + + + + signed + boolean + 0 or 1 + + (Valid only if the data is in integer format.) Whether the samples + are signed or not. + + + + width + integer + greater than 0 + + (Valid only if the data is in integer format.) The number of bits + per sample. + + + + depth + integer + greater than 0 + + (Valid only if the data is in integer format.) The number of bits + used per sample. This must be less than or equal to the width: If + the depth is less than the width, the low bits are assumed to be + the ones used. For example, a width of 32 and a depth of 24 means + that each sample is stored in a 32 bit word, but only the low 24 + bits are actually used. + + + + layout + string + gfloat + + (Valid only if the data is in float format.) A string representing + the way in which the floating point data is represented. + + + + intercept + float + any, normally 0 + + (Valid only if the data is in float format.) A floating point + value representing the value that the signal + centers on. + + + + slope + float + any, normally 1.0 + + (Valid only if the data is in float format.) A floating point + value representing how far the signal deviates from the intercept. + A slope of 1.0 and an intercept of 0.0 would mean an audio signal + with minimum and maximum values of -1.0 and 1.0. A slope of + 0.5 and intercept of 0.5 would represent values in the range 0.0 + to 1.0. + + + + + + + audio/mp3 + + Audio data compressed using the mp3 encoding scheme. + + 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. + + + + bitrate + integer + greater than 0 + + The bitrate, in kilobits per second. For VBR (variable bitrate) + mp3 data, this is the average bitrate. + + + + channels + integer + greater than 0 + + The number of channels of audio data present. + + + + joint-stereo + boolean + 0 or 1 + + If true, this implies that stereo data is stored as a combined + signal and the difference between the signals, rather than as two + entirely separate signals. If true, the channels + attribute must not be zero. + + + + + + + audio/x-ogg + + Audio data compressed using the Ogg Vorbis encoding scheme. + + + + + + FIXME: There are currently no parameters defined for this type. + + + + + + + video/raw + + Raw video data. + + fourcc + FOURCC code + + + A FOURCC code identifying the format in which this data is stored. + FOURCC (Four Character Code) is a simple system to allow + unambiguous identification of a video datastream format. See + http://www.webartz.com/fourcc/ + + + + width + integer + greater than 0 + + The number of pixels wide that each video frame is. + + + + height + integer + greater than 0 + + The number of pixels high that each video frame is. + + + + + + + video/mpeg + + Video data compressed using an MPEG encoding scheme. + + + + + + FIXME: There are currently no parameters defined for this type. + + + + + + + video/avi + + Video data compressed using the AVI encoding scheme. + + + + + + FIXME: There are currently no parameters defined for this type. + + + + + +
+
+
+ + + + + Events + + Events are a special type of data in &GStreamer;. + Events indicate some sort of notable event that has + happened somewhere in an element's pipeline. Just like any other data + type, an event comes to an element through its pads. Events are contained + in a GstBuffer, so an event buffer will contain + only an event, not any other type of data. + + + See the &GstLibRef; for the current implementation details of a GstEvent. + + +
\ No newline at end of file diff --git a/docs/pwg/intro-preface.xml b/docs/pwg/intro-preface.xml new file mode 100644 index 0000000000..45c20c4dc8 --- /dev/null +++ b/docs/pwg/intro-preface.xml @@ -0,0 +1,192 @@ + + + + + Preface + + + + + 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 documentation available on the &GStreamer; web site, + particularly the documents available in the &GStreamer; wiki. + + + Since &GStreamer; adheres to the GObject programming model, this guide + also assumes that you understand the basics of GObject + programming. There are several good introductions to the GObject library, + including the GTK+ Tutorial. + + + + + + + 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. This part covers all the + different steps you have to perform to build a basic audio filter + plugin. The discussion begins by giving examples of generating the + basic structures with . Then you + will learn how to write the code to get a basic filter plugin working. + Several chapters cover these concepts, including , , + , and . + + + After you have finished these chapters, you will have a working + plugin, but your new plugin might not have all the functionality you + need. To provide some standard functionality, you will learn how to + add features to a filter in the chapters on and . Finally, you will learn to test your + new plugin in . + + + + + — + 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 , + , , , and . Since these features are more advanced, + the chapters can basically be read in any order, as you need the + features for your custom plugins. + + + + + — Explanation + of writing source and sink plugins. Although the concepts introduced + in the two previous parts of this guide apply to filter plugins, many + of the concepts apply equally to source and sink plugins. This part + will take a look at creating source and sink type plugins for + &GStreamer; in the chapters on and + . The chapter on describes writing autoplugger + plugins. + + + + + — The + appendices contain some information that stubbornly refused to fit + cleanly in other sections of this guide, like the and . FIXME: organize better. + + + + + + The remainder of this introductory part presents a short overview of the + basic concepts involved in &GStreamer; plugin development. People familiar + with the &GstAppDevMan; can use this short overview to refresh their + memory. Topics covered include , + , , , + and . + + + + 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 mime-types to the registry along with typedetect functions. + This will allow your plugin to operate on a completely new media type. + + + + + Creating custom schedulers when the default schedulers are + insufficient. + + + + + Creating custom autopluggers when the default ones are insufficient + for your needs. + + + + + diff --git a/docs/pwg/magic-pdf b/docs/pwg/magic-pdf new file mode 100644 index 0000000000..abc274e270 --- /dev/null +++ b/docs/pwg/magic-pdf @@ -0,0 +1 @@ + diff --git a/docs/pwg/magic-png b/docs/pwg/magic-png new file mode 100644 index 0000000000..6941e28950 --- /dev/null +++ b/docs/pwg/magic-png @@ -0,0 +1 @@ + diff --git a/docs/pwg/other-autoplugger.xml b/docs/pwg/other-autoplugger.xml new file mode 100644 index 0000000000..627d15f067 --- /dev/null +++ b/docs/pwg/other-autoplugger.xml @@ -0,0 +1,9 @@ + + + + + Writing an Autoplugger + + FIXME: write. + + diff --git a/docs/pwg/other-sink.xml b/docs/pwg/other-sink.xml new file mode 100644 index 0000000000..af2a31038e --- /dev/null +++ b/docs/pwg/other-sink.xml @@ -0,0 +1,9 @@ + + + + + Writing a Sink + + FIXME: write. + + diff --git a/docs/pwg/other-source.xml b/docs/pwg/other-source.xml new file mode 100644 index 0000000000..bb991d26af --- /dev/null +++ b/docs/pwg/other-source.xml @@ -0,0 +1,9 @@ + + + + + Writing a Source + + FIXME: write. + + diff --git a/docs/pwg/titlepage.xml b/docs/pwg/titlepage.xml new file mode 100644 index 0000000000..e4a58e2450 --- /dev/null +++ b/docs/pwg/titlepage.xml @@ -0,0 +1,58 @@ + + + + + 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 + + + + + + + + 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 + +