mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 05:01:23 +00:00
More docs (most of them just empty...)
Original commit message from CVS: More docs (most of them just empty...) Added automatic pad plugging. Added automatic dynamic pad plugging. Changed some codecs to correctly set their pad types.
This commit is contained in:
parent
3cff190b74
commit
a703c01d94
19 changed files with 736 additions and 32 deletions
318
docs/manual/advanced.sgml
Normal file
318
docs/manual/advanced.sgml
Normal file
|
@ -0,0 +1,318 @@
|
|||
<chapter id="cha-advanced">
|
||||
<title>Threads</title>
|
||||
<para>
|
||||
The small application we created in the previous chapter used the
|
||||
concept of a factory to create the elements. In this chapter we will
|
||||
show you how to use the factory concepts.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>The problems with the helloworld example</title>
|
||||
<para>
|
||||
If we take a look at how the elements were created in the previous
|
||||
example we used a rather crude mechanism:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
...
|
||||
/* now it's time to get the parser */
|
||||
parse = gst_elementfactory_make("mp3parse","parse");
|
||||
decoder = gst_elementfactory_make("mpg123","decoder");
|
||||
...
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
While this mechanism is quite effective it also has one big problems:
|
||||
The elements are created base on their name. Indeed, we create an
|
||||
element mpg123 by explicitly stating the mpg123 elements name.
|
||||
Our little program therefore always uses the mpg123 decoder element
|
||||
to decode the MP3 audio stream, even if there are 3 other MP3 decoders
|
||||
in the system. We will see how we can use a more general way to create
|
||||
an MP3 decoder element.
|
||||
</para>
|
||||
<para>
|
||||
We have to introduce the concept of MIME types added to the source and
|
||||
sink pads.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>MIME Types</title>
|
||||
<para>
|
||||
GStreamer uses MIME types to indentify the different types of data
|
||||
that can be handled by the elements. They are the high level
|
||||
mechanisms to make sure that everyone is talking about the right
|
||||
kind of data.
|
||||
</para>
|
||||
<para>
|
||||
A MIME (Multipurpose Internet Mail Extension) types are a set of
|
||||
string that donote a certain type of data. examples include:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
audio/raw : raw audio samples
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
audio/mpeg : mpeg audio
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
video/mpeg : mpeg video
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
An element must associate a MIME 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.
|
||||
This allows for very dynamic and extensible element creation as we
|
||||
will see.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In our helloworld example the elements we constructed would have the
|
||||
following MIME types associated with their source and sink pads:
|
||||
</para>
|
||||
<para>
|
||||
We will see how you can create an element based on the MIME types
|
||||
of its source and sink pads. This way the end-user will have the
|
||||
ability to choose his/her favorite audio/mpeg decoder without
|
||||
you even having to care about it.
|
||||
</para>
|
||||
<para>
|
||||
The typing of the source and sink pads also makes it possible to
|
||||
'autoplug' a pipeline. We will have the ability to say: "construct
|
||||
me a pipeline that does an audio/mpeg to audio/raw conversion".
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
The basic GStreamer library does not try to solve all of your
|
||||
autoplug problems. It leaves the hard decisions to the application
|
||||
programmer, where they belong.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>GStreamer types</title>
|
||||
<para>
|
||||
GStreamer assigns a unique number to all registered MIME types. It
|
||||
also maintains a list of all elements that either uses this type
|
||||
as a source or as a sink. GStreamer also keeps a reference to
|
||||
a function that can be used to determine if a given buffer is of
|
||||
the given MIME type.
|
||||
</para>
|
||||
<para>
|
||||
There is also an association between a MIME type and a file
|
||||
extension.
|
||||
</para>
|
||||
<para>
|
||||
The type information is maintained in a list of
|
||||
<classname>GstType</classname>. The definition of a
|
||||
<classname>GstType</classname> is like:
|
||||
</para>
|
||||
<programlisting>
|
||||
typedef gboolean (*GstTypeFindFunc) (GstBuffer *buf,gpointer *priv);
|
||||
|
||||
typedef struct _GstType GstType;
|
||||
|
||||
struct _GstType {
|
||||
guint16 id; /* type id (assigned) */
|
||||
|
||||
gchar *mime; /* MIME type */
|
||||
gchar *exts; /* space-delimited list of extensions */
|
||||
|
||||
GstTypeFindFunc typefindfunc; /* typefind function */
|
||||
|
||||
GList *srcs; /* list of src objects for this type */
|
||||
GList *sinks; /* list of sink objects for type */
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
All operations on <classname>GstType</classname> occur via their
|
||||
<classname>guint16 id</classname> numbers, with <classname>GstType</classname>
|
||||
structure private to the GStreamer library.
|
||||
</para>
|
||||
|
||||
<sect2>
|
||||
<title>MIME type to id conversion</title>
|
||||
|
||||
<para>
|
||||
We can obtain the id for a given MIME type
|
||||
with the following piece of code:
|
||||
</para>
|
||||
<programlisting>
|
||||
guint16 id;
|
||||
|
||||
id = gst_type_find_by_mime("audio/mpeg");
|
||||
</programlisting>
|
||||
<para>
|
||||
This function will return 0 if the type was not known.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to <classname>GstType</classname> conversion</title>
|
||||
<para>
|
||||
We can obtain the <classname>GstType</classname> for a given id
|
||||
with the following piece of code:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstType *type;
|
||||
|
||||
type = gst_type_find_by_id(id);
|
||||
</programlisting>
|
||||
<para>
|
||||
This function will return NULL if the id was associated with
|
||||
any known <classname>GstType</classname>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>extension to id conversion</title>
|
||||
<para>
|
||||
We can obtain the id for a given file extension
|
||||
with the following piece of code:
|
||||
</para>
|
||||
<programlisting>
|
||||
guint16 id;
|
||||
|
||||
id = gst_type_find_by_ext(".mp3");
|
||||
</programlisting>
|
||||
<para>
|
||||
This function will return 0 if the extension was not known.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to <classname>GstElementFactory</classname> conversion</title>
|
||||
<para>
|
||||
When we have obtained a given type id using one of the above methods,
|
||||
we can obtain a list of all the elements that operate on this MIME
|
||||
type or extension.
|
||||
</para>
|
||||
<para>
|
||||
Obtain a list of all the elements that use this id as source with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_srcs(id);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Obtain a list of all the elements that use this id as sink with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_sinks(id);
|
||||
</programlisting>
|
||||
<para>
|
||||
When you have a list of elements, you can simply take the first
|
||||
element of the list to obtain an appropriate element.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
As you can see, there might be a multitude of elements that
|
||||
are able to operate on video/raw types. some might include:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
an MP3 audio encoder.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
an audio sink.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
an audio resampler.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
a spectrum filter.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Depending on the application, you might want to use a different
|
||||
element. This is why GStreamer leaves that decision up to the
|
||||
application programmer.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to id path detection</title>
|
||||
<para>
|
||||
You can obtain a <classname>GList</classname> of elements that
|
||||
will transform the source id into the destination id.
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_sink_to_src(sourceid, sinkid);
|
||||
</programlisting>
|
||||
<para>
|
||||
This piece of code will give you the elements needed to construct
|
||||
a path from sourceid to sinkid. This function is mainly used in
|
||||
autoplugging the pipeline.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>creating elements with the factory</title>
|
||||
<para>
|
||||
In the previous section we described how you could obtain
|
||||
an element factory using MIME types. One the factory has been
|
||||
obtained, you can create an element using:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElementFactory *factory;
|
||||
GstElement *element;
|
||||
|
||||
// obtain the factory
|
||||
factory = ...
|
||||
|
||||
element = gst_elementfactory_create(factory, "name");
|
||||
</programlisting>
|
||||
<para>
|
||||
This way, you do not have to create elements by name which
|
||||
allows the end-user to select the elements he/she prefers for the
|
||||
given MIME types.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>GStreamer basic types</title>
|
||||
<para>
|
||||
GStreamer only has two builtin types:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
audio/raw : raw audio samples
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
video/raw and image/raw : raw video data
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
All other MIME types are maintained by the plugin elements.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
6
docs/manual/cothreads.sgml
Normal file
6
docs/manual/cothreads.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-cothreads">
|
||||
<title>Cothreads</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/dynamic.sgml
Normal file
6
docs/manual/dynamic.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-dynamic">
|
||||
<title>Dynamic pipelines</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -3,9 +3,14 @@
|
|||
<para>
|
||||
The small application we created in the previous chapter used the
|
||||
concept of a factory to create the elements. In this chapter we will
|
||||
show you how to use the factory concepts.
|
||||
show you how to use the factory concepts to create elements based
|
||||
on what they do instead of how they are called.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
We will first explain the concepts involved before we move on
|
||||
to the reworked helloworld example using autoplugging.
|
||||
</para>
|
||||
<sect1>
|
||||
<title>The problems with the helloworld example</title>
|
||||
<para>
|
||||
|
@ -194,7 +199,7 @@ struct _GstType {
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to <classname>GstElement</classname> conversion</title>
|
||||
<title>id to <classname>GstElementFactory</classname> conversion</title>
|
||||
<para>
|
||||
When we have obtained a given type id using one of the above methods,
|
||||
we can obtain a list of all the elements that operate on this MIME
|
||||
|
@ -254,7 +259,49 @@ struct _GstType {
|
|||
</note>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to id path detection</title>
|
||||
<para>
|
||||
You can obtain a <classname>GList</classname> of elements that
|
||||
will transform the source id into the destination id.
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_sink_to_src(sourceid, sinkid);
|
||||
</programlisting>
|
||||
<para>
|
||||
This piece of code will give you the elements needed to construct
|
||||
a path from sourceid to sinkid. This function is mainly used in
|
||||
autoplugging the pipeline.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>creating elements with the factory</title>
|
||||
<para>
|
||||
In the previous section we described how you could obtain
|
||||
an element factory using MIME types. One the factory has been
|
||||
obtained, you can create an element using:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElementFactory *factory;
|
||||
GstElement *element;
|
||||
|
||||
// obtain the factory
|
||||
factory = ...
|
||||
|
||||
element = gst_elementfactory_create(factory, "name");
|
||||
</programlisting>
|
||||
<para>
|
||||
This way, you do not have to create elements by name which
|
||||
allows the end-user to select the elements he/she prefers for the
|
||||
given MIME types.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>GStreamer basic types</title>
|
||||
<para>
|
||||
|
|
6
docs/manual/ghostpads.sgml
Normal file
6
docs/manual/ghostpads.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-ghostpads">
|
||||
<title>Ghostpads</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -11,8 +11,20 @@
|
|||
|
||||
<!ENTITY HELLOWORLD SYSTEM "helloworld.sgml">
|
||||
<!ENTITY FACTORIES SYSTEM "factories.sgml">
|
||||
]>
|
||||
<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.sgml">
|
||||
|
||||
<!ENTITY THREADS SYSTEM "threads.sgml">
|
||||
<!ENTITY QUEUES SYSTEM "queues.sgml">
|
||||
<!ENTITY COTHREADS SYSTEM "cothreads.sgml">
|
||||
<!ENTITY DYNAMIC SYSTEM "dynamic.sgml">
|
||||
<!ENTITY GHOSTPADS SYSTEM "ghostpads.sgml">
|
||||
<!ENTITY TYPEDETECTION SYSTEM "typedetection.sgml">
|
||||
<!ENTITY UTILITY SYSTEM "utility.sgml">
|
||||
|
||||
<!ENTITY XML SYSTEM "xml.sgml">
|
||||
<!ENTITY PLUGINS SYSTEM "plugins.sgml">
|
||||
<!ENTITY PROGRAMS SYSTEM "programs.sgml">
|
||||
]>
|
||||
|
||||
<book id="GStreamer">
|
||||
<bookinfo>
|
||||
|
@ -110,6 +122,7 @@
|
|||
|
||||
&FACTORIES;
|
||||
|
||||
&HELLOWORLD2;
|
||||
</part>
|
||||
|
||||
<!-- ############ Advanced GStreamer - part ############# -->
|
||||
|
@ -118,10 +131,27 @@
|
|||
|
||||
<partintro>
|
||||
<para>
|
||||
Wanna know more?
|
||||
In this part we will cover the more advanced features of GStreamer.
|
||||
With the basics you learned in the prevous part you should be
|
||||
able to create a 'simple' pipeline. If you want more control over
|
||||
the media types and the pipeline you should use the more
|
||||
low-level features of GStreamer.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&THREADS;
|
||||
|
||||
&QUEUES;
|
||||
|
||||
&COTHREADS;
|
||||
|
||||
&DYNAMIC;
|
||||
|
||||
&GHOSTPADS;
|
||||
|
||||
&TYPEDETECTION;
|
||||
|
||||
&UTILITY;
|
||||
</part>
|
||||
|
||||
<!-- ############ XML in GStreamer - part ############# -->
|
||||
|
@ -130,10 +160,13 @@
|
|||
|
||||
<partintro>
|
||||
<para>
|
||||
Just say how we use it...
|
||||
GStreamer has the posibility to externalize the pipelines
|
||||
you create using an XML format. You can load a previously
|
||||
created pipeline by loading the XML file.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&XML;
|
||||
</part>
|
||||
|
||||
<!-- ############ XML in GStreamer - part ############# -->
|
||||
|
@ -142,10 +175,12 @@
|
|||
|
||||
<partintro>
|
||||
<para>
|
||||
A lot of text will follow...
|
||||
In this part we will describe how you create a new plugin
|
||||
to be used in GStreamer.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&PLUGINS;
|
||||
</part>
|
||||
|
||||
<!-- ############ Appendices - part ############# -->
|
||||
|
@ -155,8 +190,12 @@
|
|||
|
||||
<partintro>
|
||||
<para>
|
||||
GStreamer comes prepackaged with a few programs.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&PROGRAMS;
|
||||
|
||||
</part>
|
||||
</book>
|
||||
|
||||
|
|
182
docs/manual/helloworld2.sgml
Normal file
182
docs/manual/helloworld2.sgml
Normal file
|
@ -0,0 +1,182 @@
|
|||
<chapter id="cha-hello2">
|
||||
<title>Your second application</title>
|
||||
<para>
|
||||
In the previous chapter we created a first version of the helloworld
|
||||
application. We then explained a better way of creating the elements
|
||||
using factories identified by MIME types.
|
||||
</para>
|
||||
<para>
|
||||
In this chapter we will introduce you to autoplugging. Using the MIME
|
||||
types of the elements GStreamer can automatically create a pipeline
|
||||
for you.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Autoplugging helloworld</title>
|
||||
<para>
|
||||
We will create a second version of the helloworld application using
|
||||
autoplugging. Its source code is considerably more easy to write and
|
||||
can also much more data types.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
static gboolean playing;
|
||||
|
||||
/* eos will be called when the src element has an end os stream */
|
||||
void eos(GstSrc *src)
|
||||
{
|
||||
g_print("have eos, quitting\n");
|
||||
|
||||
playing = FALSE;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
GstElement *disksrc, *audiosink;
|
||||
GstPipeline *pipeline;
|
||||
|
||||
if (argc != 2) {
|
||||
g_print("usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_plugin_load_all();
|
||||
g_print("\n");
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new("pipeline");
|
||||
|
||||
/* create a disk reader */
|
||||
disksrc = gst_elementfactory_make("disksrc", "disk_source");
|
||||
gtk_object_set(GTK_OBJECT(disksrc),"location", argv[1],NULL);
|
||||
gtk_signal_connect(GTK_OBJECT(disksrc),"eos",
|
||||
GTK_SIGNAL_FUNC(eos),NULL);
|
||||
|
||||
/* and an audio sink */
|
||||
audiosink = gst_elementfactory_make("audiosink", "play_audio");
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add(GST_BIN(pipeline), disksrc);
|
||||
gst_bin_add(GST_BIN(pipeline), audiosink);
|
||||
|
||||
if (!gst_pipeline_autoplug(pipeline)) {
|
||||
g_print("unable to handle stream\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* find out how to handle this bin */
|
||||
gst_bin_create_plan(GST_BIN(pipeline));
|
||||
|
||||
/* make it ready */
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_READY);
|
||||
/* start playing */
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
|
||||
|
||||
playing = TRUE;
|
||||
|
||||
while (playing) {
|
||||
gst_bin_iterate(GST_BIN(pipeline));
|
||||
}
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
|
||||
|
||||
gst_pipeline_destroy(pipeline);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
first of all, we do not use any mpg123 or mp3parse element in this example.
|
||||
In fact, we only specify a source element and a sink element and add them
|
||||
to a pipeline.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The most interesting change however is the following:
|
||||
</para>
|
||||
<programlisting>
|
||||
|
||||
...
|
||||
if (!gst_pipeline_autoplug(pipeline)) {
|
||||
g_print("unable to handle stream\n");
|
||||
exit(-1);
|
||||
}
|
||||
...
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
This piece of code does all the magic.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
The source and the sink elements will be found inside the pipeline
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Since the source has no type, a typedetection will be started on
|
||||
the source element.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The best set of elements that connect the MIME type of the source
|
||||
element to the MIME type of the sink are found.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The elements are added to the pipeline and their pads are connected.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After this autoplugging, the pipeline is ready to play. Remember that this
|
||||
pipeline will be able to playback all of the media types for which an
|
||||
appropriate plugin exists since the autoplugging is all done using MIME
|
||||
types.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
I you really want, you can use the GSteamer components to do the
|
||||
autoplugging yourself.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To compile the helloworld2 example, use:
|
||||
</para>
|
||||
<programlisting>
|
||||
gcc -Wall `gstreamer-config --cflags` `gtk-config --cflags` helloworld2.c \
|
||||
-o helloworld2 `gstreamer-config --libs` `gtk-config --libs`
|
||||
</programlisting>
|
||||
<para>
|
||||
You can run the example with (substitute helloworld.mp3 with you favorite MP3 file):
|
||||
</para>
|
||||
<programlisting>
|
||||
./helloworld2 helloworld.mp3
|
||||
</programlisting>
|
||||
<para>
|
||||
You can also try to use an AVI or MPEG file as its input. Using autoplugging,
|
||||
GStreamer will automatically figure out how to handle the stream. Remember that
|
||||
only the audio part will be played because we have only added an audiosink to
|
||||
the pipeline.
|
||||
</para>
|
||||
<programlisting>
|
||||
./helloworld2 helloworld.mpeg
|
||||
</programlisting>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
|
@ -53,6 +53,8 @@ Building apps
|
|||
MIME types
|
||||
GStreamer types
|
||||
Basic types
|
||||
Your second application
|
||||
|
||||
|
||||
|
||||
advanced concepts
|
||||
|
@ -61,24 +63,27 @@ advanced concepts
|
|||
cothreads
|
||||
dynamic pipeline construction
|
||||
ghost pads
|
||||
types
|
||||
type detection
|
||||
plugin registry
|
||||
bufferpools
|
||||
Quality of service
|
||||
utility functions
|
||||
|
||||
|
||||
XML in GStreamer
|
||||
(saving)
|
||||
(loading a pipeline)
|
||||
|
||||
Plugin development
|
||||
plugin types
|
||||
chain based
|
||||
loop based
|
||||
buffers
|
||||
metadata
|
||||
subbufers
|
||||
adding pads
|
||||
libraries
|
||||
plugin registry
|
||||
types
|
||||
type detection
|
||||
QoS messages
|
||||
clocks
|
||||
|
||||
GStreamer programs
|
||||
editor
|
||||
|
|
6
docs/manual/plugins.sgml
Normal file
6
docs/manual/plugins.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-plugins">
|
||||
<title>Plugin development</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/programs.sgml
Normal file
6
docs/manual/programs.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-programs">
|
||||
<title>Programs</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/queues.sgml
Normal file
6
docs/manual/queues.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-queues">
|
||||
<title>Queues</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/threads.sgml
Normal file
6
docs/manual/threads.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-threads">
|
||||
<title>Threads</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/typedetection.sgml
Normal file
6
docs/manual/typedetection.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-typedetection">
|
||||
<title>Typedetection</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/utility.sgml
Normal file
6
docs/manual/utility.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-utility">
|
||||
<title>Utility functions</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
6
docs/manual/xml.sgml
Normal file
6
docs/manual/xml.sgml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="cha-xml">
|
||||
<title>XML in GStreamer</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -24,8 +24,6 @@ int main(int argc,char *argv[])
|
|||
gst_plugin_load_all();
|
||||
g_print("\n");
|
||||
|
||||
gst_type_dump();
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new("pipeline");
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ static GstElementStateReturn gst_pipeline_change_state(GstElement *element);
|
|||
static void gst_pipeline_prepare(GstPipeline *pipeline);
|
||||
|
||||
static void gst_pipeline_have_type(GstSink *sink, GstSink *sink2, gpointer data);
|
||||
static void gst_pipeline_pads_autoplug(GstElement *src, GstElement *sink);
|
||||
|
||||
static GstBin *parent_class = NULL;
|
||||
//static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 };
|
||||
|
@ -160,6 +161,66 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element)
|
|||
return type_id;
|
||||
}
|
||||
|
||||
static void gst_pipeline_pads_autoplug_func(GstElement *src, GstPad *pad, GstElement *sink) {
|
||||
GList *sinkpads;
|
||||
GstPad *sinkpad;
|
||||
|
||||
g_print("gstpipeline: autoplug pad connect function type %d\n", pad->type);
|
||||
|
||||
sinkpads = gst_element_get_pad_list(sink);
|
||||
while (sinkpads) {
|
||||
sinkpad = (GstPad *)sinkpads->data;
|
||||
|
||||
// if we have a match, connect the pads
|
||||
if (sinkpad->type == pad->type && sinkpad->direction == GST_PAD_SINK && !GST_PAD_CONNECTED(sinkpad)) {
|
||||
gst_pad_connect(pad, sinkpad);
|
||||
g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", pad->name, pad->type, gst_element_get_name(src));
|
||||
g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, sinkpad->type, gst_element_get_name(sink));
|
||||
break;
|
||||
}
|
||||
sinkpads = g_list_next(sinkpads);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_pipeline_pads_autoplug(GstElement *src, GstElement *sink) {
|
||||
GList *srcpads, *sinkpads;
|
||||
gboolean connected = FALSE;
|
||||
|
||||
srcpads = gst_element_get_pad_list(src);
|
||||
|
||||
while (srcpads) {
|
||||
GstPad *srcpad = (GstPad *)srcpads->data;
|
||||
GstPad *sinkpad;
|
||||
|
||||
if (srcpad->direction == GST_PAD_SRC && !GST_PAD_CONNECTED(srcpad)) {
|
||||
|
||||
sinkpads = gst_element_get_pad_list(sink);
|
||||
// FIXME could O(n) if the types were sorted...
|
||||
while (sinkpads) {
|
||||
sinkpad = (GstPad *)sinkpads->data;
|
||||
|
||||
// if we have a match, connect the pads
|
||||
if (sinkpad->type == srcpad->type && sinkpad->direction == GST_PAD_SINK && !GST_PAD_CONNECTED(sinkpad)) {
|
||||
gst_pad_connect(srcpad, sinkpad);
|
||||
g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", srcpad->name, srcpad->type, gst_element_get_name(src));
|
||||
g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, sinkpad->type, gst_element_get_name(sink));
|
||||
connected = TRUE;
|
||||
goto end;
|
||||
}
|
||||
sinkpads = g_list_next(sinkpads);
|
||||
}
|
||||
}
|
||||
srcpads = g_list_next(srcpads);
|
||||
}
|
||||
|
||||
end:
|
||||
if (!connected) {
|
||||
g_print("gstpipeline: delaying pad connections\n");
|
||||
gtk_signal_connect(GTK_OBJECT(src),"new_pad",
|
||||
GTK_SIGNAL_FUNC(gst_pipeline_pads_autoplug_func), sink);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean gst_pipeline_autoplug(GstPipeline *pipeline) {
|
||||
GList *elements;
|
||||
GstElement *element, *srcelement, *sinkelement;
|
||||
|
@ -175,7 +236,7 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) {
|
|||
|
||||
elements = gst_bin_get_list(GST_BIN(pipeline));
|
||||
|
||||
// fase 1, find all the sinks and sources...
|
||||
// fase 1, find all the sinks and sources... FIXME need better way to do this...
|
||||
while (elements) {
|
||||
element = GST_ELEMENT(elements->data);
|
||||
|
||||
|
@ -250,10 +311,7 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) {
|
|||
element = gst_elementfactory_create(factory, factory->name);
|
||||
gst_bin_add(GST_BIN(pipeline), element);
|
||||
|
||||
// FIXME match paths to connect with MIME types instead
|
||||
// of names.
|
||||
gst_pad_connect(gst_element_get_pad(srcelement,"src"),
|
||||
gst_element_get_pad(element,"sink"));
|
||||
gst_pipeline_pads_autoplug(srcelement, element);
|
||||
|
||||
srcelement = element;
|
||||
|
||||
|
@ -263,8 +321,7 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) {
|
|||
}
|
||||
|
||||
if (complete) {
|
||||
gst_pad_connect(gst_element_get_pad(srcelement,"src"),
|
||||
gst_element_get_pad(sinkelement,"sink"));
|
||||
gst_pipeline_pads_autoplug(srcelement, sinkelement);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -282,8 +339,6 @@ static GstElementStateReturn gst_pipeline_change_state(GstElement *element) {
|
|||
switch (GST_STATE_PENDING(pipeline)) {
|
||||
case GST_STATE_READY:
|
||||
// we need to set up internal state
|
||||
g_print("preparing pipeline \"%s\" for iterations:\n",
|
||||
gst_element_get_name(GST_ELEMENT(element)));
|
||||
gst_pipeline_prepare(pipeline);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
GList *_gst_types;
|
||||
guint16 _gst_maxtype;
|
||||
|
||||
#define MAX_COST 999999
|
||||
|
||||
struct _gst_type_node
|
||||
{
|
||||
int iNode;
|
||||
|
@ -302,7 +304,7 @@ static GList *construct_path (gst_type_node *rgnNodes, gint chNode)
|
|||
GstType *type;
|
||||
GList *converters;
|
||||
|
||||
while (current != 999)
|
||||
while (current != MAX_COST)
|
||||
{
|
||||
type = gst_type_find_by_id(current);
|
||||
converters = (GList *)g_hash_table_lookup(type->converters, GUINT_TO_POINTER(src));
|
||||
|
@ -322,7 +324,7 @@ static guint gst_type_find_cost(gint src, gint dest) {
|
|||
GList *converters = (GList *)g_hash_table_lookup(type->converters, GUINT_TO_POINTER(dest));
|
||||
|
||||
if (converters) return 1;
|
||||
return 999;
|
||||
return MAX_COST;
|
||||
}
|
||||
|
||||
GList *gst_type_get_sink_to_src(guint16 sinkid, guint16 srcid) {
|
||||
|
@ -339,13 +341,13 @@ GList *gst_type_get_sink_to_src(guint16 sinkid, guint16 srcid) {
|
|||
|
||||
for (i=0; i< _gst_maxtype; i++) {
|
||||
rgnNodes[i].iNode = i;
|
||||
rgnNodes[i].iDist = 999;
|
||||
rgnNodes[i].iPrev = 999;
|
||||
rgnNodes[i].iDist = MAX_COST;
|
||||
rgnNodes[i].iPrev = MAX_COST;
|
||||
}
|
||||
rgnNodes[sinkid].iDist = 0;
|
||||
rgnNodes[sinkid].iPrev = 999;
|
||||
rgnNodes[sinkid].iPrev = MAX_COST;
|
||||
|
||||
queue = gst_type_enqueue(queue, sinkid, 0, 999);
|
||||
queue = gst_type_enqueue(queue, sinkid, 0, MAX_COST);
|
||||
|
||||
while (g_list_length(queue) > 0) {
|
||||
|
||||
|
@ -353,8 +355,8 @@ GList *gst_type_get_sink_to_src(guint16 sinkid, guint16 srcid) {
|
|||
|
||||
for (i=0; i< _gst_maxtype; i++) {
|
||||
iCost = gst_type_find_cost(iNode, i);
|
||||
if (iCost != 999) {
|
||||
if((999 == rgnNodes[i].iDist) ||
|
||||
if (iCost != MAX_COST) {
|
||||
if((MAX_COST == rgnNodes[i].iDist) ||
|
||||
(rgnNodes[i].iDist > (iCost + iDist))) {
|
||||
rgnNodes[i].iDist = iDist + iCost;
|
||||
rgnNodes[i].iPrev = iNode;
|
||||
|
|
|
@ -24,8 +24,6 @@ int main(int argc,char *argv[])
|
|||
gst_plugin_load_all();
|
||||
g_print("\n");
|
||||
|
||||
gst_type_dump();
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new("pipeline");
|
||||
|
||||
|
|
Loading…
Reference in a new issue