Things to check when writing an element
This chapter contains a fairly random selection of things to take care
of when writing an element. It's up to you how far you're going to stick
to those guidelines. However, keep in mind that when you're writing an
element and hope for it to be included in the mainstream &GStreamer;
distribution, it has to meet those requirements.
As far as possible, we will try to explain why those requirements are
set.
About states
Make sure the state of an element gets reset when going to
NULL. Ideally, this should set all
object properties to their original state. This function
should also be called from _init.
Make sure an element forgets everything
about its contained stream when going from
PAUSED to READY. In
READY, all stream states are reset. An
element that goes from PAUSED to
READY and back to
PAUSED should start reading the
stream from he start again.
People that use gst-launch for testing have
the tendency to not care about cleaning up. This is
wrong. An element should be tested using
various applications, where testing not only means to make
sure it doesn't crash
, but also to test for memory leaks
using tools such as valgrind. Elements have to
be reusable in a pipeline after having been reset.
Debugging
Elements should never use their standard
output for debugging (using functions such as printf
() or g_print ()). Instead,
elements should use the logging functions provided by &GStreamer;,
named GST_DEBUG (),
GST_LOG (), GST_INFO (),
GST_WARNING () and
GST_ERROR (). The various logging levels can
be turned on and off at runtime and can thus be used for solving
issues as they turn up. Instead of GST_LOG ()
(as an example), you can also use GST_LOG_OBJECT
() to print the object that you're logging output for.
Ideally, elements should use their own debugging category. Most
elements use the following code to do that:
GST_DEBUG_CATEGORY_STATIC (myelement_debug);
#define GST_CAT_DEFAULT myelement_debug
[..]
static void
gst_myelement_class_init (GstMyelementClass *klass)
{
[..]
GST_DEBUG_CATEGORY_INIT (myelement_debug, "myelement",
0, "My own element");
}
At runtime, you can turn on debugging using the commandline
option --gst-debug=myelement:5.
Querying, events and the like
All elements to which it applies (sources, sinks, demuxers)
should implement query functions on their pads, so that
applications and neighbour elements can request the current
position, the stream length (if known) and so on.
All elements that are event-aware (their
GST_ELEMENT_EVENT_AWARE flag is set)
should implement event handling for all
events, either specifically or using
gst_pad_event_default (). Elements that
you should handle specifically are the interrupt event, in
order to properly bail out as soon as possible if state is
changed. Events may never be dropped unless specifically
intended.
Loop-based elements should always implement event handling,
in order to prevent hangs (infinite loop) on state changes.
Testing your element
gst-launch is not a good
tool to show that your element is finished. Applications such as
Rhythmbox and Totem (for GNOME) or AmaroK (for KDE)
are. gst-launch will not
test various things such as proper clean-up on reset, interrupt
event handling, querying and so on.
Parsers and demuxers should make sure to check their input. Input
cannot be trusted. Prevent possible buffer overflows and the like.
Feel free to error out on unrecoverable stream errors. Test your
demuxer using stream corruption elements such as
breakmydata (included in gst-plugins). It
will randomly insert, delete and modify bytes in a stream, and is
therefore a good test for robustness. If your element crashes
when adding this element, your element needs fixing. If it errors
out properly, it's good enough. Ideally, it'd just continue to
work and forward data as much as possible.
Demuxers should not assume that seeking works. Be prepared to
work with unseekable input streams (e.g. network sources) as
well.
Sources and sinks should be prepared to be assigned another clock
then the one they expose themselves. Always use the provided clock
for synchronization, else you'll get A/V sync issues.