GLib-CRITICAL for use of gobject-intrspection

We provide gstreamer bindings for Nim. Gst, GstBase and GstApp are currently in use. Now I try to support the other modules as well:

salewski@nuc ~/gintrotest/tests $ ls -1 /usr/share/gir-1.0/Gst*
/usr/share/gir-1.0/Gst-1.0.gir
/usr/share/gir-1.0/GstAllocators-1.0.gir
/usr/share/gir-1.0/GstApp-1.0.gir
/usr/share/gir-1.0/GstAudio-1.0.gir
/usr/share/gir-1.0/GstBase-1.0.gir
/usr/share/gir-1.0/GstCheck-1.0.gir
/usr/share/gir-1.0/GstController-1.0.gir
/usr/share/gir-1.0/GstGL-1.0.gir
/usr/share/gir-1.0/GstInsertBin-1.0.gir
/usr/share/gir-1.0/GstMpegts-1.0.gir
/usr/share/gir-1.0/GstNet-1.0.gir
/usr/share/gir-1.0/GstPbutils-1.0.gir
/usr/share/gir-1.0/GstPlayer-1.0.gir
/usr/share/gir-1.0/GstRtp-1.0.gir
/usr/share/gir-1.0/GstRtsp-1.0.gir
/usr/share/gir-1.0/GstSdp-1.0.gir
/usr/share/gir-1.0/GstTag-1.0.gir
/usr/share/gir-1.0/GstVideo-1.0.gir
/usr/share/gir-1.0/GstWebRTC-1.0.gir

Unfortunately gobject-introspection gives a few error messages like

(process:3119): GLib-CRITICAL **: 09:08:18.074: g_array_append_vals: assertion 'array' failed

(process:3119): GLib-CRITICAL **: 09:08:18.074: g_hash_table_lookup: assertion 'hash_table != NULL' failed

(process:3119): GLib-CRITICAL **: 09:08:18.074: g_hash_table_insert_internal: assertion 'hash_table != NULL' failed

for GstVideo and GstPbutils. Debugging that is not really easy. One case seems to be related to a non existing Gtype, but for another source I have still no idea.

So the question is: Are these two modules just of such bad quality that it makes no sense to support them in bindings at all, so that I just should ignore them?

Where do these critical warnings come from?

Both modules are working fine from Rust and Python at least, but in both modules there are various types that will require manual bindings because their API can’t be expressed by gobject-introspection.

Also both contain API that could be useful for normal applications too, it’s not just API for writing plugins. For example the plugin installer API in pbutils is regularly used by applications.

Thanks for your reply.

Where do these critical warnings come from?

I don’t really know. One seems to be related with a call of gRegisteredTypeInfoGetGType(info) for GstVideo/GstEncodingProfile and another one with GstPbutils/GstVideoTimeCode.

But OK when it works for Rust and Python then we should provide them for Nim too, so I have to do some debugging.

Another question, what do you think about empty method names?

I had to add this line to the generator script to skip that method with empty name:

  if gBaseInfoGetName(mInfo).len == 0: # <method name="" c:identifier="gst_video_chroma_resample" moved-to="video_chroma_resample">
    return

So gst_video_chroma_resample() was moved and is now still reported with an empty name – I verified that by inspecting the gir file. It is the only one with empty name. Well it it easy to skip when we check for empty names.

1 Like

In your code or in gobject-introspection? Because the latter runs on the GStreamer CI and locally here without any problems.

I think you can just ignore that, but it’s a bit suboptimal and should be fixed on the GStreamer-side by also providing a properly named function in addition. I’ll take care of that later, but see https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/858 .

But you can simply ignore that in your code generator, that’s fine. The function is still available as a global GstVideo.video_chroma_resample().

In gobject-introspection. The main issue seems to be related with VideoTimeCode data type, and some sequences of gobject-introspection API calls seem to trigger the issue. I can currently not find a single API call which is problematic, seems to be sequences. Maybe I can skip that data type completely, or I may inspect the gir file and see if there is something strange.

Well, Google seems to know such type of problems:

https://gitlab.gnome.org/GNOME/pygobject/-/issues/83

Will study that later.

Maybe I should note that I am using

gstreamer-1.16.2

That is not the latest version. But compiling all the modules from sources is hard.

I just added

import gintro/gst

proc launch() =
  gst.init()

to the gen.nim generator script as recommended by the google thread. That is I added the gst.init() call at the beginning. And currently there seem to be no issues.

Can it be that for using gobject-introspection API calls we have to call gst_init()? I would expect that gobject-introspection API is independent from actual gst libs.

Of course calling gst.init() from my generator script does not work for the general case of first installation, because gst does not exist before first install. I would have to create minimal basic bindings which we can ship, same as we do for glib, gobject and gir currently. I would really like to avoid shipping an additional minimal gst.nim containing the gst_ini().

You keep using “gobject-introspection” when you mean “my bindings”. You should really stop doing that.

If you call GStreamer API—regardless of whether you’re doing it directly via the C API, or through a language binding—you need to call gst_init() first.

If you call GStreamer API

No. We are talking ONLY about bindings generation!

And for bindings generation we call only libgir, libgobject and libglib.

We use this low level module

for the generation of all the high level modules. That low level gir module contains basically only C calls to the libgir.

My current guess is that libgir calls for some reason libgst without gst_init(). I would not had expected that. Maybe for GType resolution that is necessary?

If I would be not that lazy I could provide a plain C program which uses only libgir, libgobject and libglib and demonstrates the issue. Without a direct libgst call.

Yes you need to call that or nothing will work if GStreamer APIs are called. I’m surprised you came that far without it exploding.

Also I’m wondering why you go through the libgirepository API for generating your bindings code. Most (all?) other static binding using gobject-introspection directly work on the .gir XML files instead.

Because nobody told me 5 years ago :frowning:

Well I had this discussion already with Mr Bassi recently. The short version: In 2015 I created the lowlevel GTK3 bindings from C headers. Was hard due to all the glib macros, I did it for GTK 3.12 and two later versions. Was based on a few Ruby Scripts, which broke for each new GTK version. I did it that way, because the existing GTK2 low level bindings where done that way. But low level bindings are a pain to use. Than at end of 2015 Mr Mansour did some experiments with gobject-introspection for Nim, and at the same time Mr J. Hass did it for Crystal. So I started it for Nim.

But no, I don’t think that I would do it again. Was too hard and too much work for so few users.

Yes you need to call that or nothing will work if GStreamer APIs are called. I’m surprised you came that far without it exploding.

Yes, now I wonder myself. I still don’t know why libgirepository calls libgst, ldd command called on libgirepository shows no direct connection to libgst. But it may be called dynamically with dlopen().

Calling gst_init() is easy of course. The problem is that my script still has to work when no libgst is available, and also on mac and Windows. So I have to learn how I can test for existence of a lib at runtime.

Yes, seems to work without issues when gst_init() call is used before libgir API calls are used for the gst libs.

Now I wonder: GTK itself provides a gtk_init() also, which is used in user programs when we do not use the new app style program shape. May we have to call gtk_init() too before we can use libgir API calls for bindings GENERATION? Was working without til now, but was that just luck?

Using the XML file is probably easier than using libgirepository but I guess doesn’t make sense to discuss that at this point anymore.

libgirepository is mostly for dynamic bindings, and yes it dlopen()s the corresponding libraries and calls into them.

You could call it via libgirepository :slight_smile:

I’d expect the answer to be “yes”. With libgirepository it might call into the libraries and that would usually require initialization to have happened first.

It doesn’t matter if you use libgirepository for bindings generation or something else, the underlying problem is the same: it’s not just a database but it calls into the corresponding libraries and provides API for calling the API of those libraries.

You’re not just getting access to the static type information but also everything dynamic.

A test for existence of a lib at runtime seems to be not that easy.

In my generator script I have this code:

  let typelib = gi.gIrepositoryRequire(namespace, version, cast[GIRepositoryLoadFlags](0), error)
  if typelib.isNil:
    echo "Failed to load ", namespace
    echo error.message
    echo "Maybe for your OS you have to install additional GTK related packages?"
    echo "We continue with the remaining packages..."
    return

Would it be OK to call gst_init() after the gi.gIrepositoryRequire() call?

That would be easy.

But when I have to call gst_init() before, then I have to test for existence of the lib somehow myself.

Oh yes, that is an idea!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.