gstreamer-java / gst1-java-core

Java bindings for GStreamer 1.x
GNU Lesser General Public License v3.0
194 stars 72 forks source link

How to add an external binding to a native gstreamer function ? #239

Closed VolodiaPG closed 3 years ago

VolodiaPG commented 3 years ago

Hello,

While implementing my pipeline, I came across a missing function in the Clock part of these bindings. The NTP clock is not present. Which should not be a big deal because I spotted a mechanism to add new bindings from the exterior thanks to the use of the service loader to register bindings.

So I went on and implemented the following code:

interface GstNTPClockAPI extends GstClockAPI {
    GstNTPClockAPI GSTNTPCLOCK_API = GstNative.load(GstNTPClockAPI.class);

    @CallerOwnsReturn
    Pointer ptr_gst_ntp_clock_new(String name,
                                  String address,
                                  int port,
                                  int baseTime);

    @CallerOwnsReturn
    NTPClock gst_ntp_clock_new(String name,
                               String address,
                               int port,
                               int baseTime);
}

public class NTPClock extends GstObject {

    public static final String GTYPE_NAME = "GstNtpClock";

    public NTPClock(Initializer initializer) {
        super(initializer);
    }

    public NTPClock(String name,
                    String address,
                    int port,
                    int baseTime) {
        this(Natives.initializer(GstNTPClockAPI.GSTNTPCLOCK_API.ptr_gst_ntp_clock_new(name, address, port, baseTime)));
    }
}

public class Types implements NativeObject.TypeProvider {
    @Override
    public Stream<NativeObject.TypeRegistration<?>> types() {
        return Stream.of(registration(NTPClock.class, NTPClock.GTYPE_NAME, NTPClock::new));
    }
}

And in resources/META-INF/services/org.freedesktop.gstreamer.glib.NativeObject.TypeProvider I have com.toto.types.Types, which is the path to my implementation of the TypeProvider interface.

What I have understood is that this should be sufficient to be registered by gst1-java.

The issue is that as far as I have tested, nothing happens. The service provider doesn't seem to be able to find this service. (I also tested with a small test, with the interface defined only in my maven module, and this particular case works).

My conclusions are that either:

Thank you for your consideration,

P.S. I also tried the following after some debugging in the library showed that nothing happened

 ServiceLoader<NativeObject.TypeProvider> test = ServiceLoader.load(NativeObject.TypeProvider.class);
        test.iterator().forEachRemaining(x-> System.out.println("toto"));

And it doesn't write anything on stdout.

neilcsmith-net commented 3 years ago

Yes, it's there as a safety net for unmapped things, or where you want to provide a subclass for a built-in element.

I can't check for sure right now, but IIRC I think the problem is that the file should be called org.freedesktop.gstreamer.glib.NativeObject$TypeProvider. This is something that works so much better with Java modules!

Also, be careful about your hierarchy - you should be extending Clock here I think? Type hierarchies should match between Java and GStreamer.

VolodiaPG commented 3 years ago

Thank you! That was exactly it.

I went a bit crazy testing things and simplified the hierarchy in the process.

So now everything is working except for the function I am trying to bind gst_ntp_clock_new which gives me an UnsatisfiedLinkError. This particular function is located inside gstpbutils-1.0.lib. I have seen that in GstNative the libs seem to be loaded by format (*-1.0). Is it loading all the libraries or can I add somewhere the libraries I want gst1-java to load ?

neilcsmith-net commented 3 years ago

You'll need to use the overload of GstNative::load that takes the library name then. Default is (lib)gstreamer. See eg. AppAPI.

VolodiaPG commented 3 years ago

Your help has been so valuable, thank you (again)!

I surely was a bit tired not to see the overload of the method that I was debugging in, sorry for that...

Everything is now working like a charm, and looking so clean & easy to do!

P.S. For posterity's sake: gst_ntp_clock_new is actually located inside gstnet.

neilcsmith-net commented 3 years ago

No problem. Do sign up for / use the mailing list if you have any follow up queries. I generally prefer to do support there as the answers get to a wider audience. I realise this particular feature could do with more documentation, although it is partly an escape hatch - and do be aware that relying on lowlevel APIs might break between versions.