See also the main media module documentation.
Because GStreamer uses GLib, proper OOM handling becomes virtually impossible. From GLib's memory allocation documentation: If any call to allocate memory fails, the application is terminated. This also means that there is no need to check if the call succeeded. Even though GLib will use Opera's memory allocator, it will terminate the program on an OOM condition. Overriding this behaviour is possible, but would be no better as GLib code is written under the assumption that OOM will not occur.
GStreamer internally allocates and frees its memory, the
application (Opera) has very little control over this. All memory is
freed when the MediaElement object is destroyed (at the
latest).
The maximum size and number of buffers in the queue between Opera
and GStreamer is controlled by GST_MAX_BUFFER_SIZE
and GST_MAX_QUEUE_LENGTH. There must be enough data in
the queue so that GStreamer isn't starved while waiting for Opera to
feed it the next
time. With GST_MANAGER_RUN_INTERVAL=10,
GST_MAX_BUFFER_SIZE=4096
and GST_MAX_QUEUE_LENGTH=8 the throughput is limited to
~3 MB/s which is OK for now but might not be enough in the future.
Because GStreamer runs in its own thread(s), special care is needed in order to ensure thread safety in the communiction between Opera and GStreamer. A major concern is also minimizing the number of memcpy operations, as every extra copy made significantly worsens performance. Since Opera is not internally thread safe, it is critical that memory (objects) allocated by Opera, after being passed through GStreamer, are freed in Opera's thread context. The basic recipee to make this safe:
In order to build GstMediaPlayer you need the header files from
gstreamer
and
gst-plugins-base.
In Debian/Ubuntu these are packaged as libgstreamer0.10-dev and
libgstreamer-plugins-base0.10-dev.
If Opera is unable to play a file which does play in another application using GStreamer (e.g. totem), the following command contructs a pipeline similar to that of Opera. If this command works, the problem may be within Opera. If removing the queue element marked in bold solves the problem, the reason is that GStreamer can't properly play the file without random access (i.e. seeking).
gst-launch-0.10 filesrc location=example.ogg ! queue ! decodebin2 name=decode decode. ! queue ! audioconvert ! audioresample ! volume ! autoaudiosink decode. ! queue ! ffmpegcolorspace ! videoscale ! "video/x-raw-rgb,bpp=32,depth=32,red_mask=65280,green_mask=16711680,blue_mask=4278190080,alpha_mask=255,pixel-aspect-ratio=1/1" ! ffmpegcolorspace ! autovideosink
In debug builds the Opera-specific GStreamer elements will also
produce debugging output via the GStreamer debug system. To enable
this, set the GST_DEBUG environment variable,
e.g. GST_DEBUG=opera:4,default:3. Setting
GST_DEBUG_NO_COLOR helps when debugging inside Emacs. See
the gst-launch man page for details.
Since GStreamer doesn't use Opera's memory allocator (it is not thread-safe), memory debugging is best done using Valgrind. To get meaningful results, you should:
FEATURE_MEMORY_DEBUGGING, as this interferes
with Valgrind.G_SLICE=always-malloc
in your environment, otherwise you'll get lots of spurious leak
warnings.gst.supp
is necessary to suppress "leaks" from memory allocated by GStreamer
once per process.Example command line:
G_SLICE=always-malloc valgrind --undef-value-errors=no --leak-check=full --num-callers=50 --suppressions=gst.supp --gen-suppressions=all ./desktop
Additional suppressions:
{
<GstInit>
Memcheck:Leak
...
fun:_ZL7GstInitv
}