mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-01 06:01:04 +00:00
289 lines
12 KiB
XML
289 lines
12 KiB
XML
<chapter id="chapter-bus">
|
|
<title>Bus</title>
|
|
<para>
|
|
A bus is a simple system that takes care of forwarding messages from
|
|
the streaming threads to an application in its own thread context. The
|
|
advantage of a bus is that an application does not need to be
|
|
thread-aware in order to use &GStreamer;, even though &GStreamer;
|
|
itself is heavily threaded.
|
|
</para>
|
|
<para>
|
|
Every pipeline contains a bus by default, so applications do not need
|
|
to create a bus or anything. The only thing applications should do is
|
|
set a message handler on a bus, which is similar to a signal handler
|
|
to an object. When the mainloop is running, the bus will periodically
|
|
be checked for new messages, and the callback will be called when any
|
|
message is available.
|
|
</para>
|
|
|
|
<sect1 id="section-bus-howto">
|
|
<title>How to use a bus</title>
|
|
<para>
|
|
There are two different ways to use a bus:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Run a GLib/Gtk+ main loop (or iterate the default GLib main
|
|
context yourself regularly) and attach some kind of watch to the
|
|
bus. This way the GLib main loop will check the bus for new
|
|
messages and notify you whenever there are messages.
|
|
</para>
|
|
<para>
|
|
Typically you would use <function>gst_bus_add_watch ()</function>
|
|
or <function>gst_bus_add_signal_watch ()</function> in this case.
|
|
</para>
|
|
<para>
|
|
To use a bus, attach a message handler to the bus of a pipeline
|
|
using <function>gst_bus_add_watch ()</function>. This handler will
|
|
be called whenever the pipeline emits a message to the bus. In this
|
|
handler, check the signal type (see next section) and do something
|
|
accordingly. The return value of the handler should be TRUE to
|
|
keep the handler attached to the bus, return FALSE to remove it.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Check for messages on the bus yourself. This can be done using
|
|
<function>gst_bus_peek ()</function> and/or
|
|
<function>gst_bus_poll ()</function>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<programlisting><!-- example-begin bus.c a -->
|
|
#include <gst/gst.h>
|
|
|
|
static GMainLoop *loop;
|
|
|
|
static gboolean
|
|
my_bus_callback (GstBus *bus,
|
|
GstMessage *message,
|
|
gpointer data)
|
|
{
|
|
g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
|
|
|
|
switch (GST_MESSAGE_TYPE (message)) {
|
|
case GST_MESSAGE_ERROR: {
|
|
GError *err;
|
|
gchar *debug;
|
|
|
|
gst_message_parse_error (message, &err, &debug);
|
|
g_print ("Error: %s\n", err->message);
|
|
g_error_free (err);
|
|
g_free (debug);
|
|
|
|
g_main_loop_quit (loop);
|
|
break;
|
|
}
|
|
case GST_MESSAGE_EOS:
|
|
/* end-of-stream */
|
|
g_main_loop_quit (loop);
|
|
break;
|
|
default:
|
|
/* unhandled message */
|
|
break;
|
|
}
|
|
|
|
/* we want to be notified again the next time there is a message
|
|
* on the bus, so returning TRUE (FALSE means we want to stop watching
|
|
* for messages on the bus and our callback should not be called again)
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
gint
|
|
main (gint argc,
|
|
gchar *argv[])
|
|
{
|
|
GstElement *pipeline;
|
|
GstBus *bus;
|
|
guint bus_watch_id;
|
|
|
|
/* init */
|
|
gst_init (&argc, &argv);
|
|
|
|
/* create pipeline, add handler */
|
|
pipeline = gst_pipeline_new ("my_pipeline");
|
|
|
|
/* adds a watch for new message on our pipeline's message bus to
|
|
* the default GLib main context, which is the main context that our
|
|
* GLib main loop is attached to below
|
|
*/
|
|
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
|
bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL);
|
|
gst_object_unref (bus);
|
|
<!-- example-end bus.c a -->
|
|
[..]<!-- example-begin bus.c b -->
|
|
<!-- example-begin bus.c c -->
|
|
/* create a mainloop that runs/iterates the default GLib main context
|
|
* (context NULL), in other words: makes the context check if anything
|
|
* it watches for has happened. When a message has been posted on the
|
|
* bus, the default main context will automatically call our
|
|
* my_bus_callback() function to notify us of that message.
|
|
* The main loop will be run until someone calls g_main_loop_quit()
|
|
*/
|
|
loop = g_main_loop_new (NULL, FALSE);
|
|
g_main_loop_run (loop);
|
|
|
|
/* clean up */
|
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
|
gst_object_unref (pipeline);
|
|
g_source_remove (bus_watch_id);
|
|
g_main_loop_unref (loop);
|
|
|
|
return 0;
|
|
}
|
|
<!-- example-end bus.c c -->
|
|
</programlisting>
|
|
<para>
|
|
It is important to know that the handler will be called in the thread
|
|
context of the mainloop. This means that the interaction between the
|
|
pipeline and application over the bus is
|
|
<emphasis>asynchronous</emphasis>, and thus not suited for some
|
|
real-time purposes, such as cross-fading between audio tracks, doing
|
|
(theoretically) gapless playback or video effects. All such things
|
|
should be done in the pipeline context, which is easiest by writing
|
|
a &GStreamer; plug-in. It is very useful for its primary purpose,
|
|
though: passing messages from pipeline to application.
|
|
The advantage of this approach is that all the threading that
|
|
&GStreamer; does internally is hidden from the application and the
|
|
application developer does not have to worry about thread issues at
|
|
all.
|
|
</para>
|
|
<para>
|
|
Note that if you're using the default GLib mainloop integration, you
|
|
can, instead of attaching a watch, connect to the <quote>message</quote>
|
|
signal on the bus. This way you don't have to
|
|
<function>switch()</function>
|
|
on all possible message types; just connect to the interesting signals
|
|
in form of <quote>message::<type></quote>, where <type>
|
|
is a specific message type (see the next section for an explanation of
|
|
message types).
|
|
</para>
|
|
<para>
|
|
The above snippet could then also be written as:
|
|
</para>
|
|
<programlisting>
|
|
GstBus *bus;
|
|
|
|
[..]
|
|
|
|
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline);
|
|
gst_bus_add_signal_watch (bus);
|
|
g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL);
|
|
g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL);
|
|
|
|
[..]
|
|
</programlisting>
|
|
<para>
|
|
If you aren't using GLib mainloop, the asynchronous message signals won't
|
|
be available by default. You can however install a custom sync handler
|
|
that wakes up the custom mainloop and that uses
|
|
<function>gst_bus_async_signal_func ()</function> to emit the signals.
|
|
(see also <ulink type="http"
|
|
url="&URLAPI;GstBus.html">documentation</ulink> for details)
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="section-bus-message-types">
|
|
<title>Message types</title>
|
|
<para>
|
|
&GStreamer; has a few pre-defined message types that can be passed
|
|
over the bus. The messages are extensible, however. Plug-ins can
|
|
define additional messages, and applications can decide to either
|
|
have specific code for those or ignore them. All applications are
|
|
strongly recommended to at least handle error messages by providing
|
|
visual feedback to the user.
|
|
</para>
|
|
<para>
|
|
All messages have a message source, type and timestamp. The message
|
|
source can be used to see which element emitted the message. For some
|
|
messages, for example, only the ones emitted by the top-level pipeline
|
|
will be interesting to most applications (e.g. for state-change
|
|
notifications). Below is a list of all messages and a short explanation
|
|
of what they do and how to parse message-specific content.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Error, warning and information notifications: those are used
|
|
by elements if a message should be shown to the user about the
|
|
state of the pipeline. Error messages are fatal and terminate
|
|
the data-passing. The error should be repaired to resume pipeline
|
|
activity. Warnings are not fatal, but imply a problem nevertheless.
|
|
Information messages are for non-problem notifications. All those
|
|
messages contain a <classname>GError</classname> with the main
|
|
error type and message, and optionally a debug string. Both
|
|
can be extracted using <function>gst_message_parse_error
|
|
()</function>, <function>_parse_warning ()</function> and
|
|
<function>_parse_info ()</function>. Both error and debug strings
|
|
should be freed after use.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
End-of-stream notification: this is emitted when the stream has
|
|
ended. The state of the pipeline will not change, but further
|
|
media handling will stall. Applications can use this to skip to
|
|
the next song in their playlist. After end-of-stream, it is also
|
|
possible to seek back in the stream. Playback will then continue
|
|
automatically. This message has no specific arguments.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Tags: emitted when metadata was found in the stream. This can be
|
|
emitted multiple times for a pipeline (e.g. once for descriptive
|
|
metadata such as artist name or song title, and another one for
|
|
stream-information, such as samplerate and bitrate). Applications
|
|
should cache metadata internally. <function>gst_message_parse_tag
|
|
()</function> should be used to parse the taglist, which should
|
|
be <function>gst_tag_list_unref ()</function>'ed when no longer
|
|
needed.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
State-changes: emitted after a successful state change.
|
|
<function>gst_message_parse_state_changed ()</function> can be
|
|
used to parse the old and new state of this transition.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Buffering: emitted during caching of network-streams. One can
|
|
manually extract the progress (in percent) from the message by
|
|
extracting the <quote>buffer-percent</quote> property from the
|
|
structure returned by <function>gst_message_get_structure
|
|
()</function>. See also <xref linkend="chapter-buffering"/>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Element messages: these are special messages that are unique to
|
|
certain elements and usually represent additional features. The
|
|
element's documentation should mention in detail which
|
|
element messages a particular element may send. As an example,
|
|
the 'qtdemux' QuickTime demuxer element may send a 'redirect'
|
|
element message on certain occasions if the stream contains a
|
|
redirect instruction.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Application-specific messages: any information on those can
|
|
be extracted by getting the message structure (see above) and
|
|
reading its fields. Usually these messages can safely be ignored.
|
|
</para>
|
|
<para>
|
|
Application messages are primarily meant for internal
|
|
use in applications in case the application needs to marshal
|
|
information from some thread into the main thread. This is
|
|
particularly useful when the application is making use of element
|
|
signals (as those signals will be emitted in the context of the
|
|
streaming thread).
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
</chapter>
|