The issue between appsrc and compositor

Short version is: for some reason when I am adding compositor into my pipeline, it completely looses the frames from appsrc, showing transparent emptiness instead. If you can provide me with an example for such pipeline, it will resolve my question.
appsrc name=source ! compositor ! videoconvert ! autovideosink

The longer story is that I am trying to receive an RTP stream and overlay an image on top of the received frames.
I managed to do such thing with cairo and cairoverlay, but I was not impressed with the performance. So, I thought of a better way - to generate a transparent frame and overlay it with compositor. This will decouple frame size from drawing performance, especially with upscaling done by the same compositor. Great, I thought!
But instead I am trying to make it work for like third day straight.
The full pipeline with v4l2src for testing is as follows:

"v4l2src ! video/x-raw,width=640,height=480,framerate=30/1 ! queue ! mix. "
"appsrc name=appsrc is-live=true format=GST_FORMAT_TIME caps=video/x-raw,format=RGBA,width=640,height=480,framerate=30/1 ! queue !  "
"videoconvert ! compositor name=mix sink_1::width=640 sink_1::height=480 sink_0::width=640 sink_0::height=480 sink_1::xpos=0 sink_0::xpos=640 !"
"videoconvert ! autovideosink "

But the result is just an empty left side with webcam stream on the right half. (I moved them side by side just to make sure that this is not a zheight issue)

If I remove the compositor and webcam streams so that appsrc is outputting directly, I get the image corrrectly.

"appsrc name=appsrc is-live=true format=GST_FORMAT_TIME caps=video/x-raw,format=RGBA,width=640,height=480,framerate=30/1 ! queue !  "
"videoconvert ! autovideosink "

Interesting part is that it does not matter what I am generating frames with - I tried both Python PIL and cairo, and both were outputting correctly with direct pipeline and where showing transparent emptiness with composer.
Also interesting point is that if I leave only appsrc as an input for compositor, the result window is of 0 size. If I resize it manually it still shows transparent rectangle with right proportions for (640*2)x480.

Logs are also not that usefull. In one test I took working example from here to make sure that the issue is at least reproducible, added composer to the pipeline, and it got different logs :confused:

Here are the two lines of logs from not my code (I didn’t find where to plug in to increase debug level):

GStreamer-Video:ERROR:../gstreamer/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c:2635:gst_video_aggregator_sink_event: assertion failed: (seg.format == GST_FORMAT_TIME)
Bail out! GStreamer-Video:ERROR:../gstreamer/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c:2635:gst_video_aggregator_sink_event: assertion failed: (seg.format == GST_FORMAT_TIME)

Yet in code, fixes and my fixes formats are defined seemingly correctly…

And here is the log from my code with webcamera and cairo for generating a frame:

0:00:00.138525009 22092 0x72a080000b90 WARN                 v4l2src gstv4l2src.c:993:gst_v4l2src_query:<v4l2src0> Can't give latency since framerate isn't fixated !
0:00:00.138675055 22092 0x72a080000b90 WARN              aggregator gstaggregator.c:2304:gst_aggregator_query_latency_unlocked:<mix> Latency query failed
0:00:00.138804231 22092 0x72a080001490 FIXME                default gstutils.c:4089:gst_element_decorate_stream_id_internal:<appsrc> Creating random stream-id, consider implementing a deterministic way of creating a stream-id
0:00:00.138899844 22092 0x72a080000b90 WARN                 v4l2src gstv4l2src.c:993:gst_v4l2src_query:<v4l2src0> Can't give latency since framerate isn't fixated !
0:00:00.139657721 22092 0x72a080000b90 WARN              aggregator gstaggregator.c:2304:gst_aggregator_query_latency_unlocked:<mix> Latency query failed
0:00:00.139846453 22092 0x72a080000b90 WARN                 v4l2src gstv4l2src.c:993:gst_v4l2src_query:<v4l2src0> Can't give latency since framerate isn't fixated !
0:00:00.139963435 22092 0x72a080000b90 WARN              aggregator gstaggregator.c:2304:gst_aggregator_query_latency_unlocked:<mix> Latency query failed
0:00:00.144573799 22092 0x72a080000b90 WARN                 v4l2src gstv4l2src.c:993:gst_v4l2src_query:<v4l2src0> Can't give latency since framerate isn't fixated !
0:00:00.144598188 22092 0x72a080000b90 WARN              aggregator gstaggregator.c:2304:gst_aggregator_query_latency_unlocked:<mix> Latency query failed
0:00:00.152366599 22092 0x72a080000b90 WARN                 v4l2src gstv4l2src.c:993:gst_v4l2src_query:<v4l2src0> Can't give latency since framerate isn't fixated !
0:00:00.152409830 22092 0x72a080000b90 WARN              aggregator gstaggregator.c:2304:gst_aggregator_query_latency_unlocked:<mix> Latency query failed
0:00:00.152383399 22092 0x72a080001250 WARN                    v4l2 gstv4l2object.c:4610:gst_v4l2_object_set_crop:<v4l2src0:src> VIDIOC_S_CROP failed
0:00:00.176471145 22092 0x72a080001250 WARN                    v4l2 gstv4l2object.c:3273:gst_v4l2_object_reset_compose_region:<v4l2src0:src> Failed to get default compose rectangle with VIDIOC_G_SELECTION: Invalid argument
0:00:00.250037014 22092 0x72a080000b90 FIXME               basesink gstbasesink.c:3399:gst_base_sink_default_event:<autovideosink0-actual-sink-xvimage> stream-start event without group-id. Consider implementing group-id handling in the upstream elements
0:00:00.583695721 22092 0x72a080001250 WARN                 v4l2src gstv4l2src.c:1344:gst_v4l2src_create:<v4l2src0> lost frames detected: count = 1 - ts: 0:00:00.412880774

Here is the full main function:

def main():
    Gst.init(None)
    Gst.debug_set_default_threshold(3)

    pipeline_description = (  
        "v4l2src ! video/x-raw,width=640,height=480,framerate=30/1 ! queue ! mix. "
        "appsrc name=appsrc is-live=true format=GST_FORMAT_TIME caps=video/x-raw,format=RGBA,width=640,height=480,framerate=30/1 ! queue !  "
        "videoconvert ! compositor name=mix background=1 sink_1::width=640 sink_1::height=480 sink_0::width=640 sink_0::height=480 sink_1::xpos=0 sink_0::xpos=640 !"
        "videoconvert ! autovideosink "
    )
    pipeline = Gst.parse_launch(pipeline_description)

    appsrc = pipeline.get_by_name("appsrc")
    if not appsrc:
        print("Error: Unable to find appsrc in the pipeline.")
        return

    thread = threading.Thread(target=appsrc_feed, args=(appsrc, 640, 480), daemon=True)
    thread.start()
    pipeline.set_state(Gst.State.PLAYING)

    # Run the GLib main loop to keep the pipeline running
    loop = GLib.MainLoop()
    try:
        loop.run()
    except KeyboardInterrupt:
        print("Exiting...")
    pipeline.set_state(Gst.State.NULL)

I am not that versed in gstreamer app programming (I mostly configured it from shell before), so my code originated from ChatGPT. I obviously modified it, but that will be the answer for weird decisions, if there are.

So, what is your verdict? Have I missed something, or is that some kind of a bug? Any help would be usefull, even just confirmation that I haven’t lost my mind, at this point.

For the time segment issue, in parse launch syntax, it should be:

appsrc format=time

The serialization string for GST_FORMAT_TIME being “time”.

You don’t seem to set timestamp to your buffer, but I don’t think that should be an issue, it should simply be interpreted as “ASAP”. You can always enable do-timestamp on appsrc if in doubt.

Turns out timestamping was the issue. In Matrix chat Mart Raudsepp asked to try do-timestamp=true without python handling that, and this partially solved the issue. It still fails when appsrc is the only input to the compositor, and it also fails to grab the proper frame size, so created window is zero sized. But it works enough for it to be usefull)
Here is the final pipeline. Note that I am explicitly setting the size of the sink in compositor.

"udpsrc port=5000 ! application/x-rtp,encoding-name=H264,payload=96 ! "
"rtph264depay ! avdec_h264 ! videoconvert ! compose. "
"appsrc name=appsrc is-live=true do-timestamp=true format=GST_FORMAT_TIME caps=video/x-raw,format=RGBA,width=640,height=480,framerate=30/1 ! queue ! "
“compositor name=compose sink_1::width=1280 sink_1::height=720 sink_0::zorder=0 !”
"videoconvert ! autovideosink "