mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
328 lines
14 KiB
XML
328 lines
14 KiB
XML
|
<chapter id="chapter-other-base" xreflabel="Pre-made base classes">
|
||
|
<title>Pre-made base classes</title>
|
||
|
<para>
|
||
|
So far, we've been looking at low-level concepts of creating any type of
|
||
|
&GStreamer; element. Now, let's assume that all you want is to create an
|
||
|
simple audiosink that works exactly the same as, say,
|
||
|
<quote>esdsink</quote>, or a filter that simply normalizes audio volume.
|
||
|
Such elements are very general in concept and since they do nothing
|
||
|
special, they should be easier to code than to provide your own scheduler
|
||
|
activation functions and doing complex caps negotiation. For this purpose,
|
||
|
&GStreamer; provides base classes that simplify some types of elements.
|
||
|
Those base classes will be discussed in this chapter.
|
||
|
</para>
|
||
|
|
||
|
<sect1 id="section-base-sink" xreflabel="Writing a sink">
|
||
|
<title>Writing a sink</title>
|
||
|
<para>
|
||
|
Sinks are special elements in &GStreamer;. This is because sink elements
|
||
|
have to take care of <emphasis>preroll</emphasis>, which is the process
|
||
|
that takes care that elements going into the
|
||
|
<classname>GST_STATE_PAUSED</classname> state will have buffers ready
|
||
|
after the state change. The result of this is that such elements can
|
||
|
start processing data immediately after going into the
|
||
|
<classname>GST_STATE_PLAYING</classname> state, without requiring to
|
||
|
take some time to initialize outputs or set up decoders; all that is done
|
||
|
already before the state-change to <classname>GST_STATE_PAUSED</classname>
|
||
|
successfully completes.
|
||
|
</para>
|
||
|
<para>
|
||
|
Preroll, however, is a complex process that would require the same
|
||
|
code in many elements. Therefore, sink elements can derive from the
|
||
|
<classname>GstBaseSink</classname> base-class, which does preroll and
|
||
|
a few other utility functions automatically. The derived class only
|
||
|
needs to implement a bunch of virtual functions and will work
|
||
|
automatically.
|
||
|
</para>
|
||
|
<para>
|
||
|
The <classname>GstBaseSink</classname> base-class specifies some
|
||
|
limitations on elements, though:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
It requires that the sink only has one sinkpad. Sink elements that
|
||
|
need more than one sinkpad, cannot use this base-class.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The base-class owns the pad, and specifies caps negotiation, data
|
||
|
handling, pad allocation and such functions. If you need more than
|
||
|
the ones provided as virtual functions, then you cannot use this
|
||
|
base-class.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
By implementing the <function>pad_allocate ()</function> function,
|
||
|
it is possible for upstream elements to use special memory, such
|
||
|
as memory on the X server side that only the sink can allocate, or
|
||
|
even hardware memory <function>mmap ()</function>'ed from the kernel.
|
||
|
Note that in almost all cases, you will want to subclass the
|
||
|
<classname>GstBuffer</classname> object, so that your own set of
|
||
|
functions will be called when the buffer loses its last reference.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
Sink elements can derive from <classname>GstBaseSink</classname> using
|
||
|
the usual <classname>GObject</classname> type creation voodoo, or by
|
||
|
using the convenience macro <function>GST_BOILERPLATE ()</function>:
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
GST_BOILERPLATE_FULL (GstMySink, gst_my_sink, GstBaseSink, GST_TYPE_BASE_SINK);
|
||
|
|
||
|
[..]
|
||
|
|
||
|
static void
|
||
|
gst_my_sink_class_init (GstMySinkClass * klass)
|
||
|
{
|
||
|
klass->set_caps = [..];
|
||
|
klass->render = [..];
|
||
|
[..]
|
||
|
}
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
The advantages of deriving from <classname>GstBaseSink</classname> are
|
||
|
numerous:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Derived implementations barely need to be aware of preroll, and do
|
||
|
not need to know anything about the technical implementation
|
||
|
requirements of preroll. The base-class does all the hard work.
|
||
|
</para>
|
||
|
<para>
|
||
|
Less code to write in the derived class, shared code (and thus
|
||
|
shared bugfixes).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
There are also specialized base classes for audio and video, let's look
|
||
|
at those a bit.
|
||
|
</para>
|
||
|
|
||
|
<sect2 id="section-base-audiosink" xreflabel="Writing an audio sink">
|
||
|
<title>Writing an audio sink</title>
|
||
|
<para>
|
||
|
Essentially, audio sink implementations are just a special case of a
|
||
|
general sink. There are two audio base classes that you can choose to
|
||
|
derive from, depending on your needs:
|
||
|
<classname>GstBaseAudiosink</classname> and
|
||
|
<classname>GstAudioSink</classname>. The baseaudiosink provides full
|
||
|
control over how synchronization and scheduling is handled, by using
|
||
|
a ringbuffer that the derived class controls and provides. The
|
||
|
audiosink base-class is a derived class of the baseaudiosink,
|
||
|
implementing a standard ringbuffer implementing default
|
||
|
synchronization and providing a standard audio-sample clock. Derived
|
||
|
classes of this base class merely need to provide a <function>_open
|
||
|
()</function>, <function>_close ()</function> and a <function>_write
|
||
|
()</function> function implementation, and some optional functions.
|
||
|
This should suffice for many sound-server output elements and even
|
||
|
most interfaces. More demanding audio systems, such as Jack, would
|
||
|
want to implement the <classname>GstBaseAudioSink</classname>
|
||
|
base-class.
|
||
|
</para>
|
||
|
<para>
|
||
|
The <classname>GstBaseAusioSink</classname> has little to no
|
||
|
limitations and should fit virtually every implementation, but is
|
||
|
hard to implement. The <classname>GstAudioSink</classname>, on the
|
||
|
other hand, only fits those systems with a simple <function>open
|
||
|
()</function> / <function>close ()</function> / <function>write
|
||
|
()</function> API (which practically means pretty much all of them),
|
||
|
but has the advantage that it is a lot easier to implement. The
|
||
|
benefits of this second base class are large:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Automatic synchronization, without any code in the derived class.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Also automatically provides a clock, so that other sinks (e.g. in
|
||
|
case of audio/video playback) are synchronized.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Features can be added to all audiosinks by making a change in the
|
||
|
base class, which makes maintainance easy.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Derived classes require only three small functions, plus some
|
||
|
<classname>GObject</classname> boilerplate code.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
In addition to implementing the audio base-class virtual functions,
|
||
|
derived classes can (should) also implement the
|
||
|
<classname>GstBaseSink</classname> <function>set_caps ()</function> and
|
||
|
<function>get_caps ()</function> virtual functions for negotiation.
|
||
|
</para>
|
||
|
</sect2>
|
||
|
|
||
|
<sect2 id="section-base-videosink" xreflabel="Writing a general sink">
|
||
|
<title>Writing a video sink</title>
|
||
|
<para>
|
||
|
Writing a videosink can be done using the
|
||
|
<classname>GstVideoSink</classname> base-class, which derives from
|
||
|
<classname>GstBaseSink</classname> internally. Currently, it does
|
||
|
nothing yet but add another compile dependency, so derived classes
|
||
|
will need to implement all base-sink virtual functions. When they do
|
||
|
this correctly, this will have some positive effects on the end user
|
||
|
experience with the videosink:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Because of preroll (and the <function>preroll ()</function> virtual
|
||
|
function), it is possible to display a video frame already when
|
||
|
going into the <classname>GST_STATE_PAUSED</classname> state.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
By adding new features to <classname>GstVideoSink</classname>, it
|
||
|
will be possible to add extensions to videosinks that affect all of
|
||
|
them, but only need to be coded once, which is a huge maintainance
|
||
|
benefit.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
</sect2>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="section-base-src" xreflabel="Writing a source">
|
||
|
<title>Writing a source</title>
|
||
|
<para>
|
||
|
In the previous part, particularly <xref
|
||
|
linkend="section-scheduling-randomxs"/>, we have learned that some types
|
||
|
of elements can provide random access. This applies most definitely to
|
||
|
source elements reading from a randomly seekable location, such as file
|
||
|
sources. However, other source elements may be better described as a
|
||
|
live source element, such as a camera source, an audio card source and
|
||
|
such; those are not seekable and do not provide byte-exact access. For
|
||
|
all such use cases, &GStreamer; provides two base classes:
|
||
|
<classname>GstBaseSrc</classname> for the basic source functionality, and
|
||
|
<classname>GstPushSrc</classname>, which is a non-byte exact source
|
||
|
base-class. The pushsource base class itself derives from basesource as
|
||
|
well, and thus all statements about the basesource apply to the
|
||
|
pushsource, too.
|
||
|
</para>
|
||
|
<para>
|
||
|
The basesrc class does several things automatically for derived classes,
|
||
|
so they no longer have to worry about it:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Fixes to <classname>GstBaseSrc</classname> apply to all derived
|
||
|
classes automatically.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Automatic pad activation handling, and task-wrapping in case we get
|
||
|
assigned to start a task ourselves.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
The <classname>GstBaseSrc</classname> may not be suitable for all cases,
|
||
|
though; it has limitations:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
There is one and only one sourcepad. Source elements requiring
|
||
|
multiple sourcepads cannot use this base-class.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Since the base-class owns the pad and derived classes can only
|
||
|
control it as far as the virtual functions allow, you are limited
|
||
|
to the functionality provided by the virtual functions. If you need
|
||
|
more, you cannot use this base-class.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
It is possible to use special memory, such as X server memory pointers
|
||
|
or <function>mmap ()</function>'ed memory areas, as data pointers in
|
||
|
buffers returned from the <function>create()</function> virtual function.
|
||
|
In almost all cases, you will want to subclass
|
||
|
<classname>GstBuffer</classname> so that your own set of functions can
|
||
|
be called when the buffer is destroyed.
|
||
|
</para>
|
||
|
|
||
|
<sect2 id="section-base-audiosrc" xreflabel="Writing an audio source">
|
||
|
<title>Writing an audio source</title>
|
||
|
<para>
|
||
|
An audio source is nothing more but a special case of a pushsource.
|
||
|
Audio sources would be anything that reads audio, such as a source
|
||
|
reading from a soundserver, a kernel interface (such as ALSA) or a
|
||
|
test sound / signal generator. &GStreamer; provides two base classes,
|
||
|
similar to the two audiosinks described in <xref
|
||
|
linkend="section-base-audiosink"/>; one is ringbuffer-based, and
|
||
|
requires the derived class to take care of its own scheduling,
|
||
|
synchronization and such. The other is based on this
|
||
|
<classname>GstBaseAudioSrc</classname> and is called
|
||
|
<classname>GstAudioSrc</classname>, and provides a simple
|
||
|
<function>open ()</function>, <function>close ()</function> and
|
||
|
<function>read ()</function> interface, which is rather simple to
|
||
|
implement and will suffice for most soundserver sources and audio
|
||
|
interfaces (e.g. ALSA or OSS) out there.
|
||
|
</para>
|
||
|
<para>
|
||
|
The <classname>GstAudioSrc</classname> base-class has several benefits
|
||
|
for derived classes, on top of the benefits of the
|
||
|
<classname>GstPushSrc</classname> base-class that it is based on:
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Does syncronization and provides a clock.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
New features can be added to it and will apply to all derived
|
||
|
classes automatically.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
</sect2>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="section-base-transform"
|
||
|
xreflabel="Writing a transformation element">
|
||
|
<title>Writing a transformation element</title>
|
||
|
<para>
|
||
|
A third base-class that &GStreamer; provides is the
|
||
|
<classname>GstBaseTransform</classname>. This is a base class for
|
||
|
elements with one sourcepad and one sinkpad which act as a filter
|
||
|
of some sort, such as volume changing, audio resampling, audio format
|
||
|
conversion, and so on and so on. There is quite a lot of bookkeeping
|
||
|
that such elements need to do in order for things such as buffer
|
||
|
allocation forwarding, passthrough, in-place processing and such to all
|
||
|
work correctly. This base class does all that for you, so that you just
|
||
|
need to do the actual processing.
|
||
|
</para>
|
||
|
<para>
|
||
|
Since the <classname>GstBaseTransform</classname> is based on the 1-to-1
|
||
|
model for filters, it may not apply well to elements such as decoders,
|
||
|
which may have to parse properties from the stream. Also, it will not
|
||
|
work for elements requiring more than one sourcepad or sinkpad.
|
||
|
</para>
|
||
|
</sect1>
|
||
|
</chapter>
|