Commit 552b7f32 authored by Wim Taymans's avatar Wim Taymans
Browse files

Changes to gstreamer-config to include gtk+ libs manual changes: queues,...

Changes to gstreamer-config to include gtk+ libs manual changes: queues, threads, programs gsteditor does not crash a...

Original commit message from CVS:
Changes to gstreamer-config to include gtk+ libs
manual changes: queues, threads, programs
gsteditor does not crash anymore.
gstpipline new should return a GstElement *
fixed ac3dec for new getbits
fixes to gstreamer-launch
more efficient startup for gstplay.
parent 23540ccc
......@@ -51,7 +51,7 @@
</para>
</legalnotice>
<title>GStreamer Application Development Manual</title>
<title><application>GStreamer</application> Application Development Manual</title>
</bookinfo>
......@@ -60,10 +60,10 @@
<part id="overview"><title>Overview</title>
<partintro>
<para>
The first chapter of the book gives you an overview of GStreamer
design goals. Chapter 2 rapidly covers the basics of GStreamer
The first chapter of the book gives you an overview of <application>GStreamer</application>
design goals. Chapter 2 rapidly covers the basics of <application>GStreamer</application>
programming. In chapter 3 we will move on to the examples.
Since GStreamer adheres to the GTK+ programming model, the reader is
Since <application>GStreamer</application> adheres to the GTK+ programming model, the reader is
assumed to understand the basics of GTK+.
For a gentle introduction to GTK+, you may wish to read the <emphasis>GTK+
Tutorial</emphasis> or Eric Harlow's book <emphasis>Developing Linux
......@@ -84,7 +84,7 @@
<part id="basic-concepts"><title>Basic concepts</title>
<partintro>
<para>
We will first describe the basics of the GStreamer programming by
We will first describe the basics of the <application>GStreamer</application> programming by
introducing the different objects needed to create a media pipeline.
</para>
<para>
......@@ -111,7 +111,7 @@
<partintro>
<para>
With the basic concepts out of the way, you're ready to start building a
full-scale GStreamer application.
full-scale <application>GStreamer</application> application.
</para>
<para>
We assume the reader is familiar with GTK+/GNOME programming.
......@@ -127,15 +127,15 @@
<!-- ############ Advanced GStreamer - part ############# -->
<part id="advanced"><title>Advanced GStreamer concepts</title>
<part id="advanced"><title>Advanced <application>GStreamer</application> concepts</title>
<partintro>
<para>
In this part we will cover the more advanced features of GStreamer.
In this part we will cover the more advanced features of <application>GStreamer</application>.
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.
low-level features of <application>GStreamer</application>.
</para>
</partintro>
......@@ -156,11 +156,11 @@
<!-- ############ XML in GStreamer - part ############# -->
<part id="xml-gstreamer"><title>XML in GStreamer</title>
<part id="xml-gstreamer"><title>XML in <application>GStreamer</application></title>
<partintro>
<para>
GStreamer has the posibility to externalize the pipelines
<application>GStreamer</application> 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>
......@@ -171,12 +171,12 @@
<!-- ############ XML in GStreamer - part ############# -->
<part id="plugins"><title>plugin development in GStreamer</title>
<part id="plugins"><title>plugin development in <application>GStreamer</application></title>
<partintro>
<para>
In this part we will describe how you create a new plugin
to be used in GStreamer.
to be used in <application>GStreamer</application>.
</para>
</partintro>
......@@ -190,7 +190,7 @@
<partintro>
<para>
GStreamer comes prepackaged with a few programs.
<application>GStreamer</application> comes prepackaged with a few programs.
</para>
</partintro>
......
......@@ -39,8 +39,6 @@ int main(int argc,char *argv[])
}
gst_init(&amp;argc,&amp;argv);
gst_plugin_load_all();
g_print("\n");
/* create a new bin to hold the elements */
bin = gst_bin_new("bin");
......@@ -89,6 +87,7 @@ int main(int argc,char *argv[])
gst_element_set_state(bin, GST_STATE_NULL);
gst_object_destroy(GST_OBJECT(audiosink));
gst_object_destroy(GST_OBJECT(parse));
gst_object_destroy(GST_OBJECT(decoder));
gst_object_destroy(GST_OBJECT(disksrc));
gst_object_destroy(GST_OBJECT(bin));
......@@ -120,16 +119,6 @@ int main(int argc,char *argv[])
</programlisting>
<para>
For simplicity, we are going to load all known plugins. This has the effect
that all the codecs known to GStreamer are registered to the system.
</para>
<programlisting>
...
gst_plugin_load_all();
...
</programlisting>
<para>
We are going to create 4 elements and one bin. Since all objects are
in fact elements, we can define them as:
......@@ -318,8 +307,8 @@ void eos(GstSrc *src)
To compile the helloworld example, use:
</para>
<programlisting>
gcc -Wall `gstreamer-config --cflags` `gtk-config --cflags` helloworld.c \
-o helloworld `gstreamer-config --libs` `gtk-config --libs`
gcc -Wall `gstreamer-config --cflags --libs` helloworld.c \
-o helloworld
</programlisting>
<para>
This uses the program gstreamer-config, which comes with GStreamer. This program "knows"
......
......@@ -16,7 +16,7 @@
<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.
can also handle much more data types.
</para>
<programlisting>
......@@ -25,7 +25,7 @@
static gboolean playing;
/* eos will be called when the src element has an end os stream */
/* eos will be called when the src element has an end of stream */
void eos(GstSrc *src)
{
g_print("have eos, quitting\n");
......@@ -36,7 +36,7 @@ void eos(GstSrc *src)
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
GstPipeline *pipeline;
GstElement *pipeline;
if (argc != 2) {
g_print("usage: %s &lt;filename&gt;\n", argv[0]);
......@@ -44,8 +44,6 @@ int main(int argc,char *argv[])
}
gst_init(&amp;argc,&amp;argv);
gst_plugin_load_all();
g_print("\n");
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
......@@ -63,7 +61,7 @@ int main(int argc,char *argv[])
gst_bin_add(GST_BIN(pipeline), disksrc);
gst_bin_add(GST_BIN(pipeline), audiosink);
if (!gst_pipeline_autoplug(pipeline)) {
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
g_print("unable to handle stream\n");
exit(-1);
}
......@@ -159,8 +157,8 @@ int main(int argc,char *argv[])
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`
gcc -Wall `gstreamer-config --cflags --libs` helloworld2.c \
-o helloworld2
</programlisting>
<para>
You can run the example with (substitute helloworld.mp3 with you favorite MP3 file):
......@@ -175,7 +173,7 @@ int main(int argc,char *argv[])
the pipeline.
</para>
<programlisting>
./helloworld2 helloworld.mpeg
./helloworld2 mymovie.mpeg
</programlisting>
</sect1>
......
......@@ -3,4 +3,104 @@
<para>
</para>
<sect1>
<title><command>gstreamer-config</command></title>
<para>
<command>gstreamer-config</command> is a script to get information about the installed
version of <application>GStreamer</application>.
This program "knows" what compiler switches are needed to compile programs that use
<application>GStreamer</application>.
</para>
<para>
<command>gstreamer-config</command> accepts the following options:
<itemizedlist>
<listitem>
<para>
<option>--version</option> Print the currently installed version of
<application>GStreamer</application> on the standard output.
</para>
</listitem>
<listitem>
<para>
<option>--libs</option> Print the linker flags that are necessary to link a
<application>GStreamer</application> program.
</para>
</listitem>
<listitem>
<para>
<option>--cflags</option> Print the compiler flags that are necessary to compile a
<application>GStreamer</application> program.
</para>
</listitem>
<listitem>
<para>
<option>--prefix=<replaceable>PREFIX</replaceable></option>
If specified, use <replaceable>PREFIX</replaceable> instead of the installation
prefix that <application>GStreamer</application> was built with when computing the
output for the <option>--cflags</option> and <option>--libs</option> options.
This option is also used for the exec prefix if
<option>--exec-prefix</option> was not specified. This option must be specified before any
<option>--libs</option> or <option>--cflags</option> options.
</para>
</listitem>
<listitem>
<para>
<option>--exec-prefix=<replaceable>PREFIX</replaceable></option>
If specified, use <replaceable>PREFIX</replaceable> instead of the installation exec
prefix that <application>GStreamer</application> was built with when computing the
output for the <option>--cflags</option> and <option>--libs</option> options. This option must be
specified before any <option>--libs</option> or <option>--cflags</option>
options.
</para>
</listitem>
</itemizedlist>
</para>
<para>
A simple <filename>Makefile</filename> will contain something like:
<programlisting>
CC = gcc
helloworld2: helloworld2.c
$(CC) -Wall `gstreamer-config --cflags --libs` helloworld2.c -o helloworld2
clean:
rm -f *.o helloworld2
</programlisting>
</para>
</sect1>
<sect1>
<title><command>gstreamer-register</command></title>
<para>
<command>gstreamer-register</command> is used to rebuild the database of plugins.
It is used after a new plugin has been added to the system. The plugin database
can be found in <filename>/etc/gstreamer/reg.xml</filename>.
</para>
</sect1>
<sect1>
<title><command>gstreamer-launch</command></title>
<para>
This is a tool that will construct pipelines based on a command-line
syntax.
</para>
<para>
A simple commandline looks like:
<screen>
gstreamer-launch disksrc hello.mp3 ! mp3parse ! mpg123 ! audiosink-oss
</screen>
A more complex pipeline looks like:
<screen>
gstreamer-launch disksrc redpill.vob ! css-descramble ! private_stream_1.0 ! \
(ac3parse ! ac3dec ! audiosink) video_0 ! (mpeg2dec ! videosink)
</screen>
</para>
</sect1>
</chapter>
<chapter id="cha-queues">
<title>Queues</title>
<para>
A <classname>GstQueue</classname> is an implementation of a <classname>GstConnection</classname>.
Queues can be used to connect two elements in such way that the data can
be buffered.
</para>
<para>
A buffer that is sinked to a Queue will not automatically be pushed to the
next connected element but will be buffered. It will be pushed to the next
element as soon as gst_connection_push() is called.
</para>
<para>
Queues are mostly used in conjunction with a <classname>GstThread</classname> to
provide an external connection for the thread elements. You could have one
thread feeding buffers into a <classname>GstQueue</classname> and another
thread repeadedly calling gst_connection_push() on the queue to feed its
internal elements.
</para>
<para>
Below is a figure of a two-threaded decoder. We have one thread (the main execution
thread) reading the data from a file, and another thread decoding the data.
</para>
<figure float="1" id="sec-queues-img">
<title>a two-threaded decoder with a queue</title>
<graphic fileref="images/queue" format="png"></graphic>
</figure>
</chapter>
<chapter id="cha-threads">
<title>Threads</title>
<para>
GStreamer has support for multithreading throught the use of
the <classname>GstThread</classname> object. This object is in fact
a special <classname>GstBin</classname> that will become a thread when started.
</para>
<para>
To construct a new thread you will perform something like:
</para>
<programlisting>
GstElement *my_thread;
// create the thread object
my_thread = gst_thread_new("my_thread");
g_return_if_fail(audio_thread != NULL);
// add some plugins
gst_bin_add(GST_BIN(my_thread),GST_ELEMENT(funky_src));
gst_bin_add(GST_BIN(my_thread),GST_ELEMENT(cool_effect));
// connect the elements here...
...
// prepare the thread
gst_element_set_state(GST_ELEMENT(my_thread),GST_STATE_READY);
// start playing
gst_element_set_state(GST_ELEMENT(my_thread),GST_STATE_PLAYING);
</programlisting>
<para>
The above program will create a thread with two elements in it. As soon
as it is set to the PLAYING state, the thread will start to iterate.
</para>
<note>
<para>
The thread must contain at least one element of type <classname>GstSrc</classname>
or <classname>GstConnection</classname> in order to work.
</para>
</note>
<para>
A thread will be visualised as below
</para>
<figure float="1" id="sec-threads-img">
<title>a thread</title>
<graphic fileref="images/thread" format="png"></graphic>
</figure>
<para>
As an example we show the helloworld program using a thread.
</para>
<programlisting>
#include &lt;gst/gst.h&gt;
/* eos will be called when the src element has an end os stream */
void eos(GstSrc *src, gpointer data)
{
GstThread *thread = GST_THREAD(data);
g_print("have eos, quitting\n");
/* stop the bin */
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_NULL);
gst_main_quit();
}
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
GstElement *pipeline;
GstElement *thread;
if (argc != 2) {
g_print("usage: %s &lt;filename&gt;\n", argv[0]);
exit(-1);
}
gst_init(&amp;argc,&amp;argv);
/* create a new thread to hold the elements */
thread = gst_thread_new("thread");
g_assert(thread != NULL);
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
/* create a disk reader */
disksrc = gst_elementfactory_make("disksrc", "disk_source");
g_assert(disksrc != NULL);
gtk_object_set(GTK_OBJECT(disksrc),"location", argv[1],NULL);
gtk_signal_connect(GTK_OBJECT(disksrc),"eos",
GTK_SIGNAL_FUNC(eos), thread);
/* and an audio sink */
audiosink = gst_elementfactory_make("audiosink", "play_audio");
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
gst_bin_add(GST_BIN(pipeline), disksrc);
gst_bin_add(GST_BIN(pipeline), audiosink);
/* automatically setup the pipeline */
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
g_print("unable to handle stream\n");
exit(-1);
}
/* remove the source element from the pipeline */
gst_bin_remove(GST_BIN(pipeline), disksrc);
/* insert the source element in the thread, remember a thread needs at
least one source or connection element */
gst_bin_add(GST_BIN(thread), disksrc);
/* add the pipeline to the thread too */
gst_bin_add(GST_BIN(thread), GST_ELEMENT(pipeline));
/* make it ready */
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_READY);
/* start playing */
gst_element_set_state(GST_ELEMENT(thread), GST_STATE_PLAYING);
/* do whatever you want here, the thread will be playing */
...
gst_main();
gst_pipeline_destroy(thread);
exit(0);
}
</programlisting>
</chapter>
......@@ -37,6 +37,7 @@ int main(int argc,char *argv[]) {
_gst_plugin_spew = TRUE;
gst_init(&argc,&argv);
gst_plugin_load_all();
gst_plugin_load("gstelements");
gnome_init("GST Graph Editor",VERSION,argc,argv);
appwindow = gnome_app_new("gst-editor","GST Graph Editor");
......
......@@ -120,7 +120,7 @@ static void gst_editor_set_arg(GtkObject *object,GtkArg *arg,guint id) {
switch (id) {
case ARG_NAME:
gtk_object_set(GTK_OBJECT(editor),"label",GTK_VALUE_STRING(*arg),NULL);
gst_element_set_name(GST_OBJECT(editor->pipeline),
gst_element_set_name(GST_ELEMENT(editor->pipeline),
GTK_VALUE_STRING(*arg));
break;
default:
......@@ -135,7 +135,7 @@ static void gst_editor_get_arg(GtkObject *object,GtkArg *arg,guint id) {
switch (id) {
case ARG_NAME:
GTK_VALUE_STRING(*arg) =
gst_element_get_name(GST_OBJECT(editor->pipeline));
gst_element_get_name(GST_ELEMENT(editor->pipeline));
break;
default:
arg->type = GTK_TYPE_INVALID;
......
......@@ -56,7 +56,7 @@ struct _GstEditor {
GtkFrame frame;
/* the actual pipeline to be associated with this thing */
GstPipeline *pipeline;
GstElement *pipeline;
/* the editor canvas */
GstEditorCanvas *canvas;
......
......@@ -201,6 +201,7 @@ GstElementFactory *element_select_dialog() {
elements = gst_elementfactory_get_list();
while (elements) {
element = (GstElementFactory *)(elements->data);
printf("%s %s\n", element->name, element->details->class);
/* split up the factory's class */
classes = g_strsplit(element->details->class,"/",0);
class = classes;
......
......@@ -2,7 +2,7 @@
CC = gcc
helloworld: helloworld.c
$(CC) -Wall `gstreamer-config --cflags` `gtk-config --cflags` helloworld.c -o helloworld `gstreamer-config --libs` `gtk-config --libs`
$(CC) -Wall `gstreamer-config --cflags --libs` helloworld.c -o helloworld
clean:
rm -f *.o helloworld
......
......@@ -2,7 +2,7 @@
gboolean playing;
/* eos will be called when the src element has an end os stream */
/* eos will be called when the src element has an end of stream */
void eos(GstSrc *src)
{
g_print("have eos, quitting\n");
......@@ -20,8 +20,6 @@ int main(int argc,char *argv[])
}
gst_init(&argc,&argv);
gst_plugin_load_all();
g_print("\n");
/* create a new bin to hold the elements */
bin = gst_bin_new("bin");
......@@ -40,6 +38,7 @@ int main(int argc,char *argv[])
/* add objects to the main pipeline */
gst_bin_add(GST_BIN(bin), disksrc);
gst_bin_add(GST_BIN(bin), parse);
gst_bin_add(GST_BIN(bin), decoder);
gst_bin_add(GST_BIN(bin), audiosink);
......@@ -69,6 +68,7 @@ int main(int argc,char *argv[])
gst_element_set_state(bin, GST_STATE_NULL);
gst_object_destroy(GST_OBJECT(audiosink));
gst_object_destroy(GST_OBJECT(parse));
gst_object_destroy(GST_OBJECT(decoder));
gst_object_destroy(GST_OBJECT(disksrc));
gst_object_destroy(GST_OBJECT(bin));
......
......@@ -2,7 +2,7 @@
CC = gcc
helloworld2: helloworld2.c
$(CC) -Wall `gstreamer-config --cflags` `gtk-config --cflags` helloworld2.c -o helloworld2 `gstreamer-config --libs` `gtk-config --libs`
$(CC) -Wall `gstreamer-config --cflags --libs` helloworld2.c -o helloworld2
clean:
rm -f *.o helloworld2
......
......@@ -2,7 +2,7 @@
static gboolean playing;
/* eos will be called when the src element has an end os stream */
/* eos will be called when the src element has an end of stream */
void eos(GstSrc *src)
{
g_print("have eos, quitting\n");
......@@ -13,7 +13,7 @@ void eos(GstSrc *src)
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
GstPipeline *pipeline;
GstElement *pipeline;
if (argc != 2) {
g_print("usage: %s <filename>\n", argv[0]);
......@@ -41,7 +41,7 @@ int main(int argc,char *argv[])
gst_bin_add(GST_BIN(pipeline), disksrc);
gst_bin_add(GST_BIN(pipeline), audiosink);
if (!gst_pipeline_autoplug(pipeline)) {
if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) {
g_print("unable to handle stream\n");
exit(-1);
}
......
......@@ -31,7 +31,7 @@ extern "C" {
#endif /* __cplusplus */
GstElementDetails gst_disksrc_details;
extern GstElementDetails gst_disksrc_details;
#define GST_TYPE_DISKSRC \
......@@ -43,7 +43,7 @@ GstElementDetails gst_disksrc_details;
#define GST_IS_DISKSRC(obj) \
(GTK_CHECK_TYPE((obj),GST_TYPE_DISKSRC))
#define GST_IS_DISKSRC_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_DISKSRC)))
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_DISKSRC))
// NOTE: per-element flags start with 16 for now
typedef enum {
......
......@@ -70,8 +70,6 @@ GstPlugin *plugin_init(GModule *module) {
GstElementFactory *factory;
int i = 0;
if (gst_plugin_find("gstelements") != NULL) return NULL;
plugin = gst_plugin_new("gstelements");
g_return_val_if_fail(plugin != NULL,NULL);
......
......@@ -57,3 +57,13 @@ void gst_init(int *argc,char **argv[]) {
gst_trace_set_default(gst_trace);
}
}
void gst_main() {
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
}