mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
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.
This commit is contained in:
parent
23540ccc52
commit
552b7f32aa
36 changed files with 361 additions and 99 deletions
|
@ -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(&argc,&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 <filename>\n", argv[0]);
|
||||
|
@ -44,8 +44,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 */
|
||||
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>
|
||||
|
|
|
@ -1,6 +1,32 @@
|
|||
<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>
|
||||
|
|
|
@ -1,6 +1,142 @@
|
|||
<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 <gst/gst.h>
|
||||
|
||||
/* 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 <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
gst_init(&argc,&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);
|
||||
|
||||
|
|
10
gst/gst.c
10
gst/gst.c
|
@ -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();
|
||||
}
|
||||
|
||||
void gst_main_quit() {
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
/* initialize GST */
|
||||
void gst_init(int *argc,char **argv[]);
|
||||
|
||||
void gst_main();
|
||||
void gst_main_quit();
|
||||
|
||||
/* debugging */
|
||||
#ifndef DEBUG
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
GstElementDetails gst_bin_details;
|
||||
extern GstElementDetails gst_bin_details;
|
||||
|
||||
|
||||
#define GST_TYPE_BIN \
|
||||
|
|
|
@ -122,6 +122,7 @@ GstElement *gst_elementfactory_create(GstElementFactory *factory,
|
|||
// create an instance of the element
|
||||
element = GST_ELEMENT(gtk_type_new(factory->type));
|
||||
g_assert(element != NULL);
|
||||
gst_object_ref(GST_OBJECT(element));
|
||||
|
||||
// attempt to set the elemenfactory class pointer if necessary
|
||||
oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
|
||||
|
|
|
@ -102,12 +102,12 @@ static void gst_pipeline_init(GstPipeline *pipeline) {
|
|||
*
|
||||
* Returns: newly created GstPipeline
|
||||
*/
|
||||
GstPipeline *gst_pipeline_new(guchar *name) {
|
||||
GstElement *gst_pipeline_new(guchar *name) {
|
||||
GstPipeline *pipeline;
|
||||
|
||||
pipeline = gtk_type_new(gst_pipeline_get_type());
|
||||
gst_element_set_name(GST_ELEMENT(pipeline),name);
|
||||
return pipeline;
|
||||
return GST_ELEMENT(pipeline);
|
||||
}
|
||||
|
||||
static void gst_pipeline_prepare(GstPipeline *pipeline) {
|
||||
|
@ -157,6 +157,7 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element)
|
|||
gst_pad_disconnect(gst_element_get_pad(element,"src"),
|
||||
gst_element_get_pad(typefind,"sink"));
|
||||
gst_bin_remove(GST_BIN(pipeline), typefind);
|
||||
gst_object_unref(GST_OBJECT(typefind));
|
||||
|
||||
return type_id;
|
||||
}
|
||||
|
@ -223,7 +224,7 @@ end:
|
|||
|
||||
gboolean gst_pipeline_autoplug(GstPipeline *pipeline) {
|
||||
GList *elements;
|
||||
GstElement *element, *srcelement, *sinkelement;
|
||||
GstElement *element, *srcelement = NULL, *sinkelement= NULL;
|
||||
GList *factories;
|
||||
GstElementFactory *factory;
|
||||
GList *src_types, *sink_types;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
GstElementDetails gst_pipeline_details;
|
||||
extern GstElementDetails gst_pipeline_details;
|
||||
|
||||
|
||||
#define GST_TYPE_PIPELINE \
|
||||
|
@ -55,7 +55,7 @@ struct _GstPipelineClass {
|
|||
};
|
||||
|
||||
GtkType gst_pipeline_get_type(void);
|
||||
GstPipeline *gst_pipeline_new(guchar *name);
|
||||
GstElement *gst_pipeline_new(guchar *name);
|
||||
#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline))
|
||||
|
||||
gboolean gst_pipeline_autoplug(GstPipeline *pipeline);
|
||||
|
|
|
@ -253,7 +253,7 @@ gboolean gst_plugin_load_absolute(gchar *name) {
|
|||
return TRUE;
|
||||
} else if (_gst_plugin_spew) {
|
||||
// if (strstr(g_module_error(),"No such") == NULL)
|
||||
gst_info("error loading plugin: %s\n",g_module_error());
|
||||
gst_info("error loading plugin: %s, reasion: %s\n", name, g_module_error());
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
|
|
@ -70,7 +70,7 @@ gst_src_class_init(GstSrcClass *klass) {
|
|||
gst_src_signals[EOS] =
|
||||
gtk_signal_new("eos",GTK_RUN_LAST,gtkobject_class->type,
|
||||
GTK_SIGNAL_OFFSET(GstSrcClass,eos),
|
||||
gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1,
|
||||
gtk_marshal_NONE__NONE,GTK_TYPE_NONE,0,
|
||||
GST_TYPE_SRC);
|
||||
gtk_object_class_add_signals(gtkobject_class,gst_src_signals,LAST_SIGNAL);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ void gst_src_signal_eos(GstSrc *src) {
|
|||
g_return_if_fail(src != NULL);
|
||||
g_return_if_fail(GST_IS_SRC(src));
|
||||
|
||||
gtk_signal_emit(GTK_OBJECT(src),gst_src_signals[EOS],src);
|
||||
gtk_signal_emit(GTK_OBJECT(src),gst_src_signals[EOS]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -217,11 +217,17 @@ static GstElementStateReturn gst_thread_change_state(GstElement *element) {
|
|||
gst_thread_signal_thread(thread);
|
||||
break;
|
||||
case GST_STATE_PAUSED:
|
||||
gst_info("gstthread: stopping thread \"%s\"\n",
|
||||
gst_info("gstthread: pausing thread \"%s\"\n",
|
||||
gst_element_get_name(GST_ELEMENT(element)));
|
||||
GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
|
||||
gst_thread_signal_thread(thread);
|
||||
break;
|
||||
case GST_STATE_NULL:
|
||||
gst_info("gstthread: stopping thread \"%s\"\n",
|
||||
gst_element_get_name(GST_ELEMENT(element)));
|
||||
GST_FLAG_SET(thread,GST_THREAD_STATE_REAPING);
|
||||
gst_thread_signal_thread(thread);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -253,7 +259,7 @@ void *gst_thread_main_loop(void *arg) {
|
|||
}
|
||||
|
||||
GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING);
|
||||
//pthread_join(thread->thread_id,0);
|
||||
pthread_join(thread->thread_id,0);
|
||||
|
||||
gst_info("gstthread: thread \"%s\" is stopped\n",
|
||||
gst_element_get_name(GST_ELEMENT(thread)));
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
GstElementDetails gst_thread_details;
|
||||
extern GstElementDetails gst_thread_details;
|
||||
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -20,17 +20,20 @@ void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
|
|||
{
|
||||
|
||||
g_print("***** a new pad %s was created\n", gst_pad_get_name(pad));
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
|
||||
// connect to audio pad
|
||||
//if (0) {
|
||||
if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0 && audio_render_queue) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
mpeg1_setup_audio_thread(pad, audio_render_queue, pipeline);
|
||||
|
||||
} else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) {
|
||||
//} else if (0) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
mpeg1_setup_video_thread(pad, video_render_queue, pipeline);
|
||||
}
|
||||
else return;
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,16 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
|
|||
GstElement *audio_thread;
|
||||
|
||||
g_print("***** a new pad %s was created\n", gst_pad_get_name(pad));
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
|
||||
// connect to audio pad
|
||||
if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
mpeg2_setup_video_thread(pad, video_render_queue, pipeline);
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
||||
return;
|
||||
}
|
||||
else if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
gst_plugin_load("ac3parse");
|
||||
gst_plugin_load("ac3dec");
|
||||
// construct internal pipeline elements
|
||||
|
@ -40,12 +41,14 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
|
|||
decode = gst_elementfactory_make("ac3dec","decode_audio");
|
||||
g_return_if_fail(decode != NULL);
|
||||
} else if (strncmp(gst_pad_get_name(pad), "subtitle_stream_4", 17) == 0) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
gst_pad_connect(pad,
|
||||
gst_element_get_pad(merge_subtitles,"subtitle"));
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
||||
return;
|
||||
}
|
||||
else if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
|
||||
gst_plugin_load("mp3parse");
|
||||
gst_plugin_load("mpg123");
|
||||
// construct internal pipeline elements
|
||||
|
@ -55,7 +58,6 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline)
|
|||
g_return_if_fail(decode != NULL);
|
||||
}
|
||||
else {
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,16 +45,16 @@ while test $# -gt 0; do
|
|||
if test $prefix -ef @builddir@ ; then
|
||||
includes=-I@builddir@
|
||||
elif test @includedir@ != /usr/include ; then
|
||||
includes=-I@includedir@
|
||||
includes=-I@includedir@
|
||||
fi
|
||||
echo $includes
|
||||
echo $includes `gtk-config --cflags`
|
||||
;;
|
||||
--libs)
|
||||
if test $prefix -ef @builddir@ ; then
|
||||
echo @builddir@/libgst.la
|
||||
echo @builddir@/libgst.la `gtk-config --libs`
|
||||
else
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lgst
|
||||
echo $libdirs -lgst `gtk-config --libs`
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ void parse(int argc,char *argv[],GstElement *parent,gint offset,gchar endchar) {
|
|||
// snag the length in advance;
|
||||
len = strlen(argv[i]);
|
||||
// if it's just a connection, pick the 'src' pad and move on
|
||||
if ((ptr = strchr(argv[i],'|')) != 0) {
|
||||
if ((ptr = strchr(argv[i],'!')) != 0) {
|
||||
// if there's a previous pad name
|
||||
if (ptr != argv[i]) {
|
||||
ptr[0] = '\0';
|
||||
|
@ -91,29 +91,18 @@ void parse(int argc,char *argv[],GstElement *parent,gint offset,gchar endchar) {
|
|||
}
|
||||
|
||||
int main(int argc,char *argv[]) {
|
||||
int t;
|
||||
GstElement *pipeline;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
gst_plugin_load_all();
|
||||
|
||||
gst_info("\n\n");
|
||||
pipeline = gst_thread_new("launch");
|
||||
|
||||
pipeline = gst_elementfactory_make("thread","launch");
|
||||
if ((t = atoi(argv[1])))
|
||||
parse(argc,argv,pipeline,2,0);
|
||||
else
|
||||
parse(argc,argv,pipeline,1,0);
|
||||
|
||||
xmlSaveFile("launch.xml",gst_xml_write(pipeline));
|
||||
parse(argc,argv,pipeline,1,0);
|
||||
|
||||
gst_element_set_state(pipeline,GST_STATE_READY);
|
||||
gst_element_set_state(pipeline,GST_STATE_PLAYING);
|
||||
|
||||
if (t)
|
||||
sleep(t);
|
||||
else
|
||||
sleep(5);
|
||||
gst_main();
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue