mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-08 13:18:52 +00:00
Original commit message from CVS: * docs/manual/advanced-autoplugging.xml: * docs/manual/advanced-clocks.xml: * docs/manual/advanced-interfaces.xml: * docs/manual/advanced-metadata.xml: * docs/manual/advanced-position.xml: * docs/manual/advanced-schedulers.xml: * docs/manual/advanced-threads.xml: * docs/manual/appendix-gnome.xml: * docs/manual/appendix-programs.xml: * docs/manual/appendix-quotes.xml: * docs/manual/autoplugging.xml: * docs/manual/basics-bins.xml: * docs/manual/basics-data.xml: * docs/manual/basics-elements.xml: * docs/manual/basics-helloworld.xml: * docs/manual/basics-init.xml: * docs/manual/basics-pads.xml: * docs/manual/basics-plugins.xml: * docs/manual/bins-api.xml: * docs/manual/bins.xml: * docs/manual/buffers-api.xml: * docs/manual/buffers.xml: * docs/manual/clocks.xml: * docs/manual/components.xml: * docs/manual/cothreads.xml: * docs/manual/debugging.xml: * docs/manual/dparams-app.xml: * docs/manual/dynamic.xml: * docs/manual/elements-api.xml: * docs/manual/elements.xml: * docs/manual/factories.xml: * docs/manual/gnome.xml: * docs/manual/goals.xml: * docs/manual/helloworld.xml: * docs/manual/helloworld2.xml: * docs/manual/highlevel-components.xml: * docs/manual/highlevel-xml.xml: * docs/manual/init-api.xml: * docs/manual/intro-basics.xml: * docs/manual/intro-motivation.xml: * docs/manual/intro-preface.xml: * docs/manual/intro.xml: * docs/manual/links-api.xml: * docs/manual/links.xml: * docs/manual/manual.xml: * docs/manual/motivation.xml: * docs/manual/pads-api.xml: * docs/manual/pads.xml: * docs/manual/plugins-api.xml: * docs/manual/plugins.xml: * docs/manual/programs.xml: * docs/manual/queues.xml: * docs/manual/quotes.xml: * docs/manual/schedulers.xml: * docs/manual/states-api.xml: * docs/manual/states.xml: * docs/manual/threads.xml: * docs/manual/typedetection.xml: * docs/manual/win32.xml: * docs/manual/xml.xml: Try 2. This time, include a short preface as a "general introduction", also add code blocks around all code samples so they get compiled. We still need a way to tell readers the filename of the code sample. In some cases, don't show all code in the documentation, but do include it in the generated code. This allows for focussing on specific bits in the docs, while still having a full test application available. * examples/manual/Makefile.am: Fix up examples for new ADM. Add several of the new examples that were either added or were missing from the build system. * examples/manual/extract.pl: Allow nameless blocks.
144 lines
5.5 KiB
XML
144 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>
|
|
|