Meta not registering in second element

Context

I’m trying to implement a (draft) profile ISOBMFF, called the NGA GEOINT Imagery Profile for ISR (GIMI). One of the requirements is a per-sample identifier in the form urn:uuid:<uuid>. I can generate it my modified mux/mp4 implementation, but it would be useful if it could be applied earlier in the processing pipeline, so analysis elements could associate the analysis results with the sample.

To do that, I’ve created a simple Meta to hold the sample identifier, and an element to put the sample identifier on, and that looks like it works.

However when I try to pull out the identifier in the mux/mp4 element, I get assertions.

Debugging

It looks like I have a similar problem to Implementing a new GstMeta,but call gst_meta_api_type_register error - #3 by ndufresne and the G_DEBUG=fatal_criticals suggestion seems to align.

I reproduce the problem on the command line, using:

gst-launch-1.0 -v videotestsrc num-buffers=250 ! video/x-raw,width=1280,height=720,format=I420 ! x264enc ! sampleidentstamper identifier-kind=urn-uuid ! gimimp4mux classification=U ! filesink location=out.mp4

In the debug output, I see: g_pointer_type_register_static: assertion 'g_type_from_name (name) == 0' failed, and the backtrace looks like this:

#0  0x00007ffff7d556a1 in g_logv () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#1  0x00007ffff7d55953 in g_log () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2  0x00007ffff7cd4042 in g_pointer_type_register_static () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#3  0x00007ffff7ec6a87 in gst_meta_api_type_register () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#4  0x00007ffff66b8383 in gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure#0} () at generic/sampleident/src/sampleidentmeta.rs:110
#5  std::sync::once_lock::{impl#0}::get_or_init::{closure#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}> () at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once_lock.rs:276
#6  std::sync::once_lock::{impl#0}::initialize::{closure#0}<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !> (p=<optimised out>)
    at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once_lock.rs:483
#7  std::sync::once::{impl#2}::call_once_force::{closure#0}<std::sync::once_lock::{impl#0}::initialize::{closure_env#0}<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !>> (p=<optimised out>) at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once.rs:217
#8  std::sys::sync::once::futex::Once::call<std::sync::once::{impl#2}::call_once_force::{closure_env#0}<std::sync::once_lock::{impl#0}::initialize::{closure_env#0}<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !>>> (self=0x7ffff67f86d0 <gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::TYPE+8>, ignore_poisoning=true, f=<optimised out>)
    at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sys/sync/once/futex.rs:124
#9  0x00007ffff66b8be1 in std::sync::once::Once::call_once_force<std::sync::once_lock::{impl#0}::initialize::{closure_env#0}<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !>> (self=<optimised out>, f=...) at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once.rs:217
#10 std::sync::once_lock::OnceLock<glib::types::Type>::initialize<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !>
    (self=<optimised out>, f=...) at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once_lock.rs:482
#11 0x00007ffff672f577 in std::sync::once_lock::OnceLock<glib::types::Type>::get_or_try_init<glib::types::Type, std::sync::once_lock::{impl#0}::get_or_init::{closure_env#0}<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>, !> (self=0x7ffff67f86c8 <gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::TYPE>, f=...) at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once_lock.rs:364
#12 std::sync::once_lock::OnceLock<glib::types::Type>::get_or_init<glib::types::Type, gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::{closure_env#0}>
    (self=0x7ffff67f86c8 <gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type::TYPE>, f=...) at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/once_lock.rs:276
#13 gstsampleident::sampleidentmeta::imp::sample_identification_meta_api_get_type () at generic/sampleident/src/sampleidentmeta.rs:109
#14 0x00007ffff66cabb4 in gstreamer::buffer::BufferRef::meta_mut<gstsampleident::sampleidentmeta::SampleIdentificationMeta> (self=0x7fffe44aa2e0) at /home/bradh/.cargo/git/checkouts/gstreamer-rs-79e52a2d27eb91a3/083c5bd/gstreamer/src/buffer.rs:571
#15 gstmp4::mp4mux::imp::MP4Mux::drain_buffers (self=0x555555856ef0, settings=<optimised out>, state=0x555555856ef8, buffers=0x7fffe8003780) at mux/mp4/src/mp4mux/imp.rs:1169
#16 0x00007ffff66d09c1 in gstmp4::mp4mux::imp::{impl#7}::aggregate (self=0x555555856ef0, _timeout=<optimised out>) at mux/mp4/src/mp4mux/imp.rs:1861

The code at mux/mp4/src/mp4mux/imp.rs:1169 (backtrace step #15) looks like:

if let Some(meta) = buffer.make_mut().meta_mut::<sampleidentmeta::SampleIdentificationMeta>() {

that appears to be calling down into the meta, where it ends up in this block:

*TYPE.get_or_init(|| unsafe {
            let t = glib::Type::from_glib(gst::ffi::gst_meta_api_type_register(
                c"GstSampleIdentificationMetaAPI".as_ptr() as *const _,
                [ptr::null::<std::os::raw::c_char>()].as_ptr() as *mut *const _,
            ));

            assert_ne!(t, glib::Type::INVALID);

            t
        })

Where the gst_meta_api_type_register() call fails. It looks like its working OK for the stamper element, but the mux isn’t working. In the related report, it was identified that the meta is registered twice, which looks possible, but I don’t understand why.

Additional details

The source for my meta is at generic/sampleident/src/sampleidentmeta.rs · cabf878cc5defa78f7f47cca079505ca3c670368 · Brad Hards / gst-plugins-rs · GitLab

The imp source for the stamper element is at generic/sampleident/src/sampleidentmeta.rs · cabf878cc5defa78f7f47cca079505ca3c670368 · Brad Hards / gst-plugins-rs · GitLab

The imp for my modified mux element is at mux/mp4/src/mp4mux/imp.rs · cabf878cc5defa78f7f47cca079505ca3c670368 · Brad Hards / gst-plugins-rs · GitLab

Questions

Is there an obvious problem with what I’m trying here?

Is there an easy fix, or an alternative approach.

Is there a way to debug this further?

g_pointer_type_register_static: assertion 'g_type_from_name (name) == 0' failed usually means that something is trying to register a GType with the same name more than once.

The mp4mux changes you mentioned don’t seem to actually use the new Meta.

For using a GstMeta from multiple plugins, you would need to implement a separate library (using the C ABI) with a C library (not plugin) that exposes the relevant GstMeta related functions. You would then need to use Rust’s FFI to access that C library in the mp4mux plugin.

Alternatively you could make use of gst::CustomMeta but that requires allocating a new gst::Structure for each meta then. That only really makes sense if the meta is specific to one plugin though (and potentially handling in other places for interaction with that plugin).