vendredi, janvier 10 2020

Rust/GStreamer paid internship at Collabora

Collabora is offering various paid internship positions for 2020. We have a nice range of very cool projects involving kernel work, Panfrost, Monado, etc.

I'll be mentoring a GStreamer project aiming to write a Chromecast sink element in Rust. It would be a great addition to GStreamer and would give the student a chance to learn about our favorite multimedia framework but also about bindings between C GObject code and Rust.

So if you're interested don't hesitate to apply or contact me if you have any question.

vendredi, mai 17 2019

Rust+GNOME hackfest in Berlin

Last week I had the chance to attend for the first time the GNOME+Rust Hackfest in Berlin. My goal was to finish the GstVideoDecoder bindings, keep learning about Rust and meet people from the GNOME/Rust community. I had some experience with gstreamer-rs as an user but never actually wrote any bindings myself. To make it even more challenging the underlying C API is unfortunatelly unsafe so we had to do some smart tricks to make it safe to use in Rust.

I'm very happy with the work I managed to do during these 4 days. I was able to complete the bindings as well as my CDG decoder using them. The bindings are waiting for final review and the decoder should hopefully be merged soon as well. More importantly I learned a lot about the bindings infrastructure but also about more advanced Rust features and nice API design patterns. Turned out it's much easier to write Rust when you are sitting next to the gtk-rs maintainers. ;)

I'm very grateful to Guillaume and Sebastian for all the time they spent answering my questions and helping fighting the Rust compiler. Thanks also to Alban for letting me stay at his place, to Zeeshan and Kinvolk for organizing and hosting the hackfest and to Collabora for sponsoring my trip.


mercredi, avril 24 2019

GStreamer buffer flow analyzer

Gstreamer's logging system is an incredibly powerful ally when debugging but it can sometimes be a bit daunting to dig through the massive amount of generated logs. I often find myself writing small scripts processing gst logs when debugging. Their goal is generally to automatically extract some specific information or metrics from the generated logs. Such scripts are usually quickly written and quickly disposed once I'm done with my debugging but I've been wondering how I could make them easier to write and to re-use.

gst-log-parser is an attempt to solve these two problems by providing a library parsing GStreamer logs and enabling users to easily build such tools. It's written in Rust and is shipped with a few tools that I wrote to track actual bugs in GStreamer elements and applications.

One of those tool is a buffer flow analyzer which can be used to provide various information regarding the buffers exchanged through your pipeline. It relies on logs generated by the upstream stats tracer, so no modification in GStreamer core or in plugins is required.

First step is to generate the logs, this is easily done by defining these env variables: GST_DEBUG="GST_TRACER:7" GST_DEBUG_FILE=gst.log GST_TRACERS=stats

We can then use flow for example to detect decreasing pts or dts:

cargo run --release --example flow gst.log check-decreasing-pts

Decreasing pts tsdemux0:audio_0_0042 00:00:02.550852023 < 00:00:02.555653845

Or to detect gaps of at least 100ms in the buffers flow:

cargo run --release --example flow gst.log gap 100

gap from udpsrc0:src : 00:00:00.100142318 since previous buffer (received: 00:00:02.924532910 previous: 00:00:02.824390592)

It can also be used to draw graphs of the pts/dts produced by each src pad over time:

cargo run --release --example flow gst.log plot-pts


These are just a few examples of the kind of information we can extract from stats logs. I'll likely add more tools in the future and I'm happy to hear suggestions about other features that would make your life easier when debugging GStreamer.

lundi, juin 20 2016

GStreamer leaks tracer

Here at Collabora we are pretty interested at improving QA tools in GStreamer. Thibault is for example doing a great job on gst-validate ensuring that a lot of code paths are regularly tested using real life scenarios. Last year I added Valgrind support to gst-validate allowing us to automatically detect memory leaks in test scenarios. My goal was to integrate this as part of GStreamer's automatic QA to prevent memory leak regressions. While this can sometimes be a good approach to track leaks it has a few downsides:

  • Valgrind can be very CPU and/or memory consuming which can be a problem with longer scenarios or on limited hardware such as embedded devices.
  • As a result running the full tests suite with valgrind can take ages.
  • Valgrind checks for any potential memory leak which can lead to a lot of false positives or leaks in low level system libraries on which we have few control. We usually work around this problem using suppression files but they are generally very fragile and depend a lot on the system/distribution which has been used for testing.

I tried to solve these issues by trying a new approach using GstTracer. Tracers are a new mechanism introduced in GStreamer 1.8 allowing tools to hook into GStreamer internals and collect data. So I started by adding tracer hooks when GstObject and GstMiniObject are created and destroyed. Then I implemented a new tracer tracking the lifetime of (mini)objects and listing those which are still alive when the application is exiting. This worked pretty well but I needed a way to discard objects which are intentionally leaked (false positives). To do so I introduced a new (mini)object flag allowing us to mark such objects.

I'm pretty happy with the result, while proof testing this tool I found and fixed dozens of leaks into Gstreamer (core, plugins and tests). Some of those fixes have already reached the 1.8.2 release. It's also very easy to use and doesn't require any external tool unlike Valgrind (which can be tricky to integrate on some platforms).

To use it you just have to load the leaks tracer with your application and enable tracer logs:

GST_TRACERS="leaks" GST_DEBUG="GST_TRACER:7" gst-launch-1.0 videotestsrc num-buffers=10 ! fakesink

You can also filter out the types of GstObject or GstMiniObject tracked to reduce memory consumption:

GST_TRACERS="leaks(GstEvent,GstMessage)"  GST_DEBUG="GST_TRACER:7" gst-launch-1.0 videotestsrc num-buffers=10 ! fakesink

This tracer has recently be merged into GStreamer core and will be part of the 1.9.1 release.

As future enhancements I implemented live tracking and checkpointing support using signals like I already did in gobject-list a while ago. I'd also like to be able to display the creation stack trace of leaked objects to easily spot the leaked instances. Finally, I opened a bug to discuss the integration of the tracer with the QA system.

lundi, mars 30 2015

Tracking the reference count of a GstMiniObject using gdb

As part of my work at Collabora, I'm currently adding Valgrind support to the awesome gst-validate tool. The ultimate goal is to run our hundreds of GStreamer tests inside Valgrind as part of the existing QA infrastructure to automatically track memory related regressions (invalid reads, leaks, etc).

Most of the gst-validate changes have already landed and can be very easily used by passing the --valgrind argument to gst-validate-launcher. I'm now focusing on making sure most of our existing tests are passing with Valgrind which means doing quite a lot of memory leaks debugging (everyone love doing those right?).

A lot of GStreamer types are based on GstMiniObject instead of the usual GObject. It makes a lot of sense from a performance pov but can make tracking ref count issues harder as we can't rely on tools such as RefDbg or gobject-list.

I was tracking one GstMiniObject leak today and was looking for a way to get a trace each time its reference is modified. We can use GST_DEBUG="GST_REFCOUNTING:9" to get logs each time the object is reffed/unreffed but I was actually interested in the full stack trace. With to the help of the French gang (kudos to Dodji, Bastien and Christophe!) I managed to do so using this good old gdb.

First thing is to break when the object you want to track is created, you can either do this by using in gdb b mysource:line or just add a G_BREAKPOINT() in your source code. Start your app with gdb as usual then uses:

set logging on
set pagination off

The ouput can be pretty long so this will ensure that logs are saved to a file (gdb.txt by default) and that gdb won't bother you asking for confirmation before printing ouput. Now start your app (run) and once it has paused use the following command:

watch -location ((GstMiniObject*)caps)->refcount

caps is the name of the instance of the object I want to track, as defined in the scope where I installed my breakpoint; update it to match yours. This command adds a watchpoint on the refcount of the object, that means gdb will now stop each time its value is modified. The -location option ensures that gdb watches the memory associated with the expression, not using it would limit us to the local scope of the variable.

Now we want to display a backtrace each time gdb pauses when this watchpoint is hit. This is done using commands:


All the gdb instructions between commands and end will be automatically executed each time gdb pauses because of the watchpoint we just defined. In our case we first want to display a stack trace (bt) and then continue the execution of the program.

We are now all set, we just have to ask gdb to resume the normal execution of the program we are debugging:


This should generate a gdb.txt log file containing something like:

Old value = 1
New value = 2
gst_mini_object_ref (mini_object=0x7ffff001c8f0) at gstminiobject.c:362
362	  return mini_object;
#0  0x00007ffff6f384ed in gst_mini_object_ref (mini_object=0x7ffff001c8f0) at gstminiobject.c:362
#1  0x00007ffff6f38b00 in gst_mini_object_replace (olddata=0x7ffff67f0c58, newdata=0x7ffff001c8f0) at gstminiobject.c:501
#2  0x00007ffff72573ed in gst_caps_replace (old_caps=0x7ffff67f0c58, new_caps=0x7ffff001c8f0) at ../../../gst/gstcaps.h:312
#3  0x00007ffff72578fa in helper_find_suggest (data=0x7ffff67f0c30, probability=GST_TYPE_FIND_MAXIMUM, caps=0x7ffff001c8f0) at gsttypefindhelper.c:230
#4  0x00007ffff6f7d606 in gst_type_find_suggest_simple (find=0x7ffff67f0bf0, probability=100, media_type=0x7ffff5de8a66 "video/mpegts", fieldname=0x7ffff5de8a4e "systemstream") at gsttypefind.c:197
#5  0x00007ffff5ddbec3 in mpeg_ts_type_find (tf=0x7ffff67f0bf0, unused=<optimized out>) at gsttypefindfunctions.c:2381
#6  0x00007ffff6f7dbc7 in gst_type_find_factory_call_function (factory=0x6dbbc0 [GstTypeFindFactory], find=0x7ffff67f0bf0) at gsttypefindfactory.c:215
#7  0x00007ffff7257d83 in gst_type_find_helper_get_range (obj=0x7e8280 [GstProxyPad], parent=0x7d0500 [GstGhostPad], func=0x7ffff6f2aa37 <gst_proxy_pad_getrange_default>, size=10420224, extension=0x7ffff00010e0 "MTS", prob=0x7ffff67f0d04) at gsttypefindhelper.c:355
#8  0x00007ffff683fd43 in gst_type_find_element_loop (pad=0x7e47d0 [GstPad]) at gsttypefindelement.c:1064
#9  0x00007ffff6f79895 in gst_task_func (task=0x7ef050 [GstTask]) at gsttask.c:331
#10 0x00007ffff6f7a971 in default_func (tdata=0x61ac70, pool=0x619910 [GstTaskPool]) at gsttaskpool.c:68
#11 0x0000003ebb070d68 in g_thread_pool_thread_proxy (data=<optimized out>) at gthreadpool.c:307
#12 0x0000003ebb0703d5 in g_thread_proxy (data=0x7ceca0) at gthread.c:764
#13 0x0000003eb880752a in start_thread (arg=0x7ffff67f1700) at pthread_create.c:310
#14 0x0000003eb850022d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Hardware watchpoint 1: -location ((GstMiniObject*)caps)->refcount

Old value = 2
New value = 1
0x00007ffff6f388b6 in gst_mini_object_unref (mini_object=0x7ffff001c8f0) at gstminiobject.c:442
442	  if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
#0  0x00007ffff6f388b6 in gst_mini_object_unref (mini_object=0x7ffff001c8f0) at gstminiobject.c:442
#1  0x00007ffff6f7d027 in gst_caps_unref (caps=0x7ffff001c8f0) at ../gst/gstcaps.h:230
#2  0x00007ffff6f7d615 in gst_type_find_suggest_simple (find=0x7ffff67f0bf0, probability=100, media_type=0x7ffff5de8a66 "video/mpegts", fieldname=0x7ffff5de8a4e "systemstream") at gsttypefind.c:198
#3  0x00007ffff5ddbec3 in mpeg_ts_type_find (tf=0x7ffff67f0bf0, unused=<optimized out>) at gsttypefindfunctions.c:2381
#4  0x00007ffff6f7dbc7 in gst_type_find_factory_call_function (factory=0x6dbbc0 [GstTypeFindFactory], find=0x7ffff67f0bf0) at gsttypefindfactory.c:215
#5  0x00007ffff7257d83 in gst_type_find_helper_get_range (obj=0x7e8280 [GstProxyPad], parent=0x7d0500 [GstGhostPad], func=0x7ffff6f2aa37 <gst_proxy_pad_getrange_default>, size=10420224, extension=0x7ffff00010e0 "MTS", prob=0x7ffff67f0d04) at gsttypefindhelper.c:355
#6  0x00007ffff683fd43 in gst_type_find_element_loop (pad=0x7e47d0 [GstPad]) at gsttypefindelement.c:1064
#7  0x00007ffff6f79895 in gst_task_func (task=0x7ef050 [GstTask]) at gsttask.c:331
#8  0x00007ffff6f7a971 in default_func (tdata=0x61ac70, pool=0x619910 [GstTaskPool]) at gsttaskpool.c:68
#9  0x0000003ebb070d68 in g_thread_pool_thread_proxy (data=<optimized out>) at gthreadpool.c:307
#10 0x0000003ebb0703d5 in g_thread_proxy (data=0x7ceca0) at gthread.c:764
#11 0x0000003eb880752a in start_thread (arg=0x7ffff67f1700) at pthread_create.c:310
#12 0x0000003eb850022d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Hardware watchpoint 1: -location ((GstMiniObject*)caps)->refcount

If you see this kind of error in your log

Error evaluating expression for watchpoint 1 value has been optimized out

this means you may have to rebuild your application and/or its libraries without any optimization. This is pretty easy with autotools:

make clean
CFLAGS="-g3 -ggdb3 -O0" make

Now all you need is to grab a good cup of tea and start digging through this log to find your leak. Good fun!


Daniel pointed out to me that watchpoints can be pretty unreliable in gdb. So here is another version where we ask gdb to break when our object is reffed/unreffed. You just have to figure out its address using gdb or simply by printing the value of its pointer.

b gst_mini_object_ref if (mini_object == 0xdeadbeef)
b gst_mini_object_unref if (mini_object == 0xdeadbeef)
commands 1 2

jeudi, décembre 18 2014

Kernel hacking workshop

As part of our "community" program at Collabora, I've had the chance to attend to a workshop on kernel hacking at UrLab (the ULB hackerspace). I never touched any part of the kernel and always saw it as a scary thing for hardcore hackers wearing huge beards, so this was a great opportunity to demystify the beast.

We learned about how to create and build modules, interact with userspace using the /sys pseudo-filesystem and some simple tasks with the kernel internal library (memory management, linked lists, etc). The second part was about the old school /dev system and how to implement a character device.

I also discovered which is a great tool for browsing and find your way through a huge code base. It's definitely the kind of tool I'd consider re-using for other projects.

So a very a cool experience, I'm still not seeing myself submitting kernel patches any time soon but may consider trying to implement a simple driver or something if I ever need to. Thanks a lot to UrLab for hosting the event, to Collabora for letting me attend and of course to Hastake who did a great job explaining all this and providing fun exercises (I had to reboot only 3 times! But yeah, next time I'll use a VM :) )

kernel-workshop.jpg Club Mate, kernel hacking and bulgur

vendredi, novembre 8 2013

Building a single GNOME module using jhbuild

I often see new contributors (and even seasoned hackers) wanting to hack on a GNOME module, say Empathy, trying to build it using:

jhbuild build empathy

This is obviously correct but asks jhbuild to build not only Empathy but also all its dependencies (62 modules) so you'll end up building most of the GNOME stack. While building a full GNOME stack may sometimes be useful that's generally not needed and definitely not the easiest and fastest way to proceed.

Here is what I usually do.

First I make sure to have installed all the dependencies of the module using your distribution packaging system. This is done on Fedora using:

sudo yum-builddep empathy

or on Ubuntu/Debian:

sudo apt-get build-dep empathy

If you are using a recent distribution, there are good chances that most of these dependencies are still recent enough to build the module you want to hack on. Of course, as you are trying to build the master branch of the project some dependencies may have been bumped to one of the latest developement releases. But first let's try to build just Empathy.

jhbuild buildone empathy

There are good chances that some dependencies are missing or are too old, you'll then see this kind of error message:

No package 'libsecret-1' found
Requested 'telepathy-glib >= 0.19.9' but version of Telepathy-GLib is 0.18.2

That means you'll have to build these two libraries in your jhbuild as well. Just check the list of depencies of the module to find the exact name of the module:

jhbuild list empathy | grep secret
jhbuild list empathy | grep telepathy

In this example you'll see you have to build the libsecret and telepathy-glib modules:

jhbuild buildone libsecret telepathy-glib

Of course these modules may have some extra depencies on their own so you may have to do some iteration of this process before being able to actually build the module you care about. But, from my experience, if you are using a recent distribution (like the latest Fedora release) the whole process will still be much faster than building the full stack. Furthermore, it will save you to have to deal with build errors from potentially 62 modules.

lundi, septembre 17 2012

GNOME 3.6 Brussels party

Next week GNOME 3.6 will be released upon the world. That's the perfect excuse to meet the day after the release (Thursday 27th) and share some beers together. All the infos are on the wiki.

lundi, juillet 30 2012

Empathy BoF at GUADEC

I'll lead an Empathy BoF session tomorrow (Tuesday) from 4 to 6 (room 2.2a) feel free to show up if you are interested about the recent redesign work we have done in Empathy and our plans for the future.

Btw, a bunch of people have asked me about two annoying Telepathy issues:

 * GTalk contacts not showing up. That's actually a telepathy-glib bug which has been fixed in 0.18.2. If you are running F17 you can upgrade by grabbing the package from updates-testing: yum --enablerepo=updates-testing update telepathy-glib
 * Not being able to chat with 'People Nearby' contacts. Turns out that's because of Fedora's stupid firewall blocking incoming connections; disabling the firewall should make you reachable with Salut.

vendredi, juin 15 2012

New Empathy contact list

I've been working for a while implementing a new Empathy contact list and I'm happy to announce that this work just reached master! It's based on a brand new design from Allan; I'm pretty happy with the result as it looks pretty similar to the mockups.

This new contact list has been implemented using Alexander's awesome EggListBox. This new GTK+ container has been extracted from Contacts to its own git repository to be easily usable by other applications using git submodule or subtree. If you've ever cursed at GtkTreeView for being such a pain to use you should really give it a try. It's a delight to use: you can pack any GtkWidget in it and so don't have to use GtkTreeModel and GtkCellRenderer any more.

New Empathy roster - no group

One of the goals of this new design is to unify the way contacts are presented to users across the whole GNOME desktop, which is why it looks pretty similar to Contacts. We also wanted to make it look 'cleaner' so presence statuses are now only displayed if the contact explicitly defined one. Groups have been disabled by default as most users don't really use them (they are not as useful as they used to be as you can quickly find any contact using the integrated live search) but can easily be re-enabled in the preferences dialog.

A very nice feature of this new roster are the 'top contacts' which are always displayed at the top of the contact list. It contains the contacts you tagged as 'favourite' but also the contacts you to talk most often. This is done using Folks's Zeitgeist integration[1].

New Empathy roster - groups

I want to thanks all the people involved especially Alexander for his help with EggListBox, Allan for his design, Seif for the Zeitgeist integration, Danielle who reviewed my code, Intel who funded parts of the Folks and Zeitgeist work and of course Collabora who sponsored most of this work.


[1] It's actually disabled atm as we are waiting for a Folks release which should happen soon

lundi, avril 16 2012

GNOME 3.4 Brussels party this Thursday at 'Chaff'

GNOME 3.4 has been released since a short while and we didn't find the time to properly celebrate it here in Brussels. It's time to fix this critical mistake and so I'm glad to announce the GNOME Brussels Beer 3.4 party this Thursday. Feel free to join us if you're around and want to share some beers with us.

lundi, janvier 16 2012

GNOME Beer event at FOSDEM 2012

Despite what some stats may say, my biggest contribution to GNOME is not in bugs or code but in the organization of beer related events!

So I'm pleased to announce that, like each year, we'll have a GNOME Beer party on the Saturday night of FOSDEM (4th Feb). People seemed happy of the location of last year, so we decided to stay at "La Bécasse" in the city center. Feel free to add yourself to the wiki if you are planning to attend.

See you at FOSDEM!

mardi, septembre 27 2011

Calling phone numbers in GNOME 3.2

One of my favourite feature of my N900 is the ability to very easily call a contact using my SIP account. Calling phone numbers in Empathy through SIP is possible since a while using the New Call dialog but you have to enter the number manually which can be annoying. Thanks to Folks's evolution-data-server backend, GNOME 3.2 will allow you to very easily call contacts from your address book!

First step is to mark a SIP account as being able to call phone numbers. We added an option for that in the accounts dialog.


Then if an IM contact is linked to an Evolution one having at least a phone field, you can call him from the contact list! Soon you should be able to call IM contacts publishing their phone numbers in their personal personal info as well.


You can also call any contact using gnome-contact directly; just click on the phone icon next to the phone number.

gnome contacts

This is pretty cool because thanks to gnome-shell's contact integration it's now easier than ever to call a contact. Just search for him in the Shell overview and then start the call from gnome-contacts. That's the kind of integration we were aiming for when we started the Telepathy and Folks projects and it's great to see that we are finally getting there!

jeudi, septembre 15 2011

GNOME Brussels Beer 3.2

It's been a while since our first beer event and the GNOME 3.0 release party so I'm please to announce that the GNOME Brussels Beer 3.2 event will be the 22th Sept (next Thursday).

As you can see I synced the version with GNOME releases as a I think it's a good idea to have at least one per release. :)

So if you're around, feel free to add your name on the event page and join us!

See you there!

lundi, août 29 2011

Shiny new UI in Empathy 3.2

One of our main goals during this developement cycle was to continue improving Empathy's user experience by re-designing different parts of the UI. To do so our Empathy team at Collabora worked closely with designers from the awesome GNOME Design Team.

The log viewer has been completely re-written based on an original design from Matthew Paul Thomas (Canonical). As you can see, this new log viewer now displays calls and offers different options to easily search through the mass of logs.

Empathy 3.2 will also introduce a whole new experimental user interface for audio and video calls designed by Nick Richards (Intel). The new UI is based on Clutter and allows users to select the webcam and microphone used during the call, move the video preview around, etc. It should also gain support for video effects once Raluca finishes integrating her work with Nick's design. This new UI will be optional in 3.2 as it relies on new Telepathy API but will definitely become the default as soon as those API are stabilised.

Not actually me

I have to say that working closely with designers is a really enjoyable experience. It's good to have people to ask to when we are unsure about the best way to present a feature or an option to users. I'm really looking forward to continuing to improve Empathy with them.

jeudi, août 11 2011

GNOME IM integration BoF today at 4

As some people have to leave earlier today, the GNOME IM Integration BoF will a start at 4 rather than 5 today. See you there, room 1.204

vendredi, août 5 2011

Desktop Summit schedule on your N900

Thanks to Olivier and Will you can very easily check the full schedule of the Desktop Summit on your N900. Just install the latest version of sojourner and enjoy!

GNOME IM integration BoF during the Desktop Summit

Like 36 other Collaborans, I'm going to attend to the Desktop Summit in Berlin.

I'll lead the GNOME IM integration BoF session on Thursday. It will basically be a follow up of our Hackfest in June so if you are interested into instant messaging integration in GNOME feel free to join us.

mardi, avril 12 2011

GNOME 3.0 Brussels party this Wednesday at 'Chaff'

The GNOME 3.0 Brussels Launch Party will be this Wednesday at Chaff (the same place where we did our first GNOME beer event) from 6:30 pm.

We'll order food around 8 and we'll have a bunch of GNOME 3 goodies to give away.

I know it's pretty short notice, sorry for that, but we had some troubles to find a place. We were initially looking for a place that would have allowed us to do some presentations but didn't find any. Anyway, we'll have beers which is certainly the most important thing. :)

See you there!

mercredi, mars 16 2011

New Empathy icon!

Since its first release, Empathy was using the Telepathy logo as icon.

This icon suffers different problems, the main ones being its look in smaller sizes. Also, 2 blue heads may not be the best way to present an IM client to users.

So, after lot of discussions and different propositions, Empathy has now, thanks to Jakub Steiner, a new icon! As you can see, we now have slightly different versions depending on the size.

I hope you'll like it!

- page 1 de 5