mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 05:31:15 +00:00
145 lines
5.5 KiB
XML
145 lines
5.5 KiB
XML
|
<chapter id="chapter-queryevents">
|
||
|
<title>Position tracking and seeking</title>
|
||
|
|
||
|
<para>
|
||
|
So far, we've looked at how to create a pipeline to do media processing
|
||
|
and how to make it run ("iterate"). Most application developers will be
|
||
|
interested in providing feedback to the user on media progress. Media
|
||
|
players, for example, will want to show a slider showing the progress in
|
||
|
the song, and usually also a label indicating stream length. Transcoding
|
||
|
applications will want to show a progress bar on how much % of the task
|
||
|
is done. &GStreamer; has built-in support for doing all this using a
|
||
|
concept known as <emphasis>querying</emphasis>. Since seeking is very
|
||
|
similar, it will be discussed here as well. Seeking is done using the
|
||
|
concept of <emphasis>events</emphasis>.
|
||
|
</para>
|
||
|
|
||
|
<sect1 id="section-querying">
|
||
|
<title>Querying: getting the position or length of a stream</title>
|
||
|
|
||
|
<para>
|
||
|
Querying is defined as requesting a specific stream-property related
|
||
|
to progress tracking. This includes getting the length of a stream (if
|
||
|
available) or getting the current position. Those stream properties
|
||
|
can be retrieved in various formats such as time, audio samples, video
|
||
|
frames or bytes. The functions used are <function>gst_element_query
|
||
|
()</function> and <function>gst_pad_query ()</function>.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
Obviously, using either of the above-mentioned functions requires the
|
||
|
application to know <emphasis>which</emphasis> element or pad to run
|
||
|
the query on. This is tricky, but there are some good sides to the
|
||
|
story. The good thing is that elements (or, rather, pads - since
|
||
|
<function>gst_element_query ()</function> internally calls
|
||
|
<function>gst_pad_query ()</function>) forward (<quote>dispatch</quote>)
|
||
|
events and queries to peer pads (or elements) if they don't handle it
|
||
|
themselves. The bad side is that some elements (or pads) will handle
|
||
|
events, but not the specific formats that you want, and therefore it
|
||
|
still won't work.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
Most queries will, fortunately, work fine. Queries are always
|
||
|
dispatched backwards. This means, effectively, that it's easiest to
|
||
|
run the query on your video or audio output element, and it will take
|
||
|
care of dispatching the query to the element that knows the answer
|
||
|
(such as the current position or the media length; usually the demuxer
|
||
|
or decoder).
|
||
|
</para>
|
||
|
|
||
|
<programlisting><!-- example-begin query.c a -->
|
||
|
#include <gst/gst.h>
|
||
|
|
||
|
gint
|
||
|
main (gint argc,
|
||
|
gchar *argv[])
|
||
|
{
|
||
|
GstElement *sink, *pipeline;
|
||
|
<!-- example-end query.c a -->
|
||
|
[..]<!-- example-begin query.c b --><!--
|
||
|
gchar *l;
|
||
|
|
||
|
/* init */
|
||
|
gst_init (&argc, &argv);
|
||
|
|
||
|
/* args */
|
||
|
if (argc != 2) {
|
||
|
g_print ("Usage: %s <filename>\n", argv[0]);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* build pipeline, the easy way */
|
||
|
l = g_strdup_printf ("filesrc location=\"%s\" ! oggdemux ! vorbisdec ! "
|
||
|
"audioconvert ! audioscale ! alsasink name=a",
|
||
|
argv[1]);
|
||
|
pipeline = gst_parse_launch (l, NULL);
|
||
|
sink = gst_bin_get_by_name (GST_BIN (pipeline), "a");
|
||
|
g_free (l);
|
||
|
|
||
|
/* play */
|
||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||
|
--><!-- example-end query.c b -->
|
||
|
<!-- example-begin query.c c -->
|
||
|
/* run pipeline */
|
||
|
do {
|
||
|
gint64 len, pos;
|
||
|
GstFormat fmt = GST_FORMAT_TIME;
|
||
|
|
||
|
if (gst_element_query (sink, GST_QUERY_POSITION, &fmt, &pos) &&
|
||
|
gst_element_query (sink, GST_QUERY_TOTAL, &fmt, &len)) {
|
||
|
g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
|
||
|
GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
|
||
|
}
|
||
|
} while (gst_bin_iterate (GST_BIN (pipeline)));
|
||
|
<!-- example-end query.c c -->
|
||
|
[..]<!-- example-begin query.c d --><!--
|
||
|
/* clean up */
|
||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||
|
|
||
|
return 0;
|
||
|
--><!-- example-end query.c d -->
|
||
|
<!-- example-begin query.c e -->
|
||
|
}
|
||
|
<!-- example-end query.c e --></programlisting>
|
||
|
<para>
|
||
|
If you are having problems with the dispatching behaviour, your best
|
||
|
bet is to manually decide which element to start running the query on.
|
||
|
You can get a list of supported formats and query-types with
|
||
|
<function>gst_element_get_query_types ()</function> and
|
||
|
<function>gst_element_get_formats ()</function>.
|
||
|
</para>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="section-eventsseek">
|
||
|
<title>Events: seeking (and more)</title>
|
||
|
|
||
|
<para>
|
||
|
Events work in a very similar way as queries. Dispatching, for
|
||
|
example, works exactly the same for events (and also has the same
|
||
|
limitations). Although there are more ways in which applications
|
||
|
and elements can interact using events, we will only focus on seeking
|
||
|
here. This is done using the seek-event. A seek-event contains a
|
||
|
seeking offset, a seek method (which indicates relative to what the
|
||
|
offset was given), a seek format (which is the unit of the offset,
|
||
|
e.g. time, audio samples, video frames or bytes) and optionally a
|
||
|
set of seeking-related flags (e.g. whether internal buffers should be
|
||
|
flushed). The behaviour of a seek is also wrapped in the function
|
||
|
<function>gst_element_seek ()</function>.
|
||
|
</para>
|
||
|
|
||
|
<programlisting>
|
||
|
static void
|
||
|
seek_to_time (GstElement *audiosink,
|
||
|
gint64 time_nanonseconds)
|
||
|
{
|
||
|
gst_element_seek (audiosink,
|
||
|
GST_SEEK_METHOD_SET | GST_FORMAT_TIME |
|
||
|
GST_SEEK_FLAG_FLUSH, time_nanoseconds);
|
||
|
}
|
||
|
</programlisting>
|
||
|
</sect1>
|
||
|
</chapter>
|
||
|
|