</para>
</legalnotice>
- <title>GStreamer Application Development Manual</title>
+ <title><application>GStreamer</application> Application Development Manual</title>
</bookinfo>
<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
<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>
<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.
<!-- ############ 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>
<!-- ############ 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>
<!-- ############ 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>
<partintro>
<para>
- GStreamer comes prepackaged with a few programs.
+ <application>GStreamer</application> comes prepackaged with a few programs.
</para>
</partintro>
}
gst_init(&argc,&argv);
- gst_plugin_load_all();
- g_print("\n");
/* create a new bin to hold the elements */
bin = gst_bin_new("bin");
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));
</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:
</para>
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"
<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>
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");
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
- GstPipeline *pipeline;
+ GstElement *pipeline;
if (argc != 2) {
g_print("usage: %s <filename>\n", argv[0]);
}
gst_init(&argc,&argv);
- gst_plugin_load_all();
- g_print("\n");
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
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);
}
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):
the pipeline.
</para>
<programlisting>
- ./helloworld2 helloworld.mpeg
+ ./helloworld2 mymovie.mpeg
</programlisting>
</sect1>
<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 <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>
_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");
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:
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;
GtkFrame frame;
/* the actual pipeline to be associated with this thing */
- GstPipeline *pipeline;
+ GstElement *pipeline;
/* the editor canvas */
GstEditorCanvas *canvas;
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;
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
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");
}
gst_init(&argc,&argv);
- gst_plugin_load_all();
- g_print("\n");
/* create a new bin to hold the elements */
bin = gst_bin_new("bin");
/* 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);
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));
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
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");
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
- GstPipeline *pipeline;
+ GstElement *pipeline;
if (argc != 2) {
g_print("usage: %s <filename>\n", argv[0]);
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);
}
#endif /* __cplusplus */
-GstElementDetails gst_disksrc_details;
+extern GstElementDetails gst_disksrc_details;
#define GST_TYPE_DISKSRC \
#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 {
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);
gst_trace_set_default(gst_trace);
}
}
+
+void gst_main() {
+ gdk_threads_enter();
+ gtk_main();
+ gdk_threads_leave();
+}
+
+void gst_main_quit() {
+ gtk_main_quit();
+}
/* initialize GST */
void gst_init(int *argc,char **argv[]);
+void gst_main();
+void gst_main_quit();
+
/* debugging */
#ifndef DEBUG
#ifdef DEBUG_ENABLED
extern "C" {
#endif /* __cplusplus */
-GstElementDetails gst_bin_details;
+extern GstElementDetails gst_bin_details;
#define GST_TYPE_BIN \
// 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);
*
* 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) {
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;
}
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;
extern "C" {
#endif /* __cplusplus */
-GstElementDetails gst_pipeline_details;
+extern GstElementDetails gst_pipeline_details;
#define GST_TYPE_PIPELINE \
};
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);
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;
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);
}
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]);
}
/**
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;
}
}
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)));
extern "C" {
#endif /* __cplusplus */
-GstElementDetails gst_thread_details;
+extern GstElementDetails gst_thread_details;
typedef enum {
{
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);
}
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
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
g_return_if_fail(decode != NULL);
}
else {
- gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
return;
}
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
;;
*)
#endif /* __cplusplus */
-GstElementDetails gst_disksrc_details;
+extern GstElementDetails gst_disksrc_details;
#define GST_TYPE_DISKSRC \
#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 {
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);
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
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");
}
gst_init(&argc,&argv);
- gst_plugin_load_all();
- g_print("\n");
/* create a new bin to hold the elements */
bin = gst_bin_new("bin");
/* 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);
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));
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
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");
int main(int argc,char *argv[])
{
GstElement *disksrc, *audiosink;
- GstPipeline *pipeline;
+ GstElement *pipeline;
if (argc != 2) {
g_print("usage: %s <filename>\n", argv[0]);
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);
}
// 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';
}
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;
}