Nvoverlaysink ignores properties when pipeline is restarted

Just seen on Nx with devkit with:

$ cat /etc/nv_tegra_release 
# R32 (release), REVISION: 5.1, GCID: 27362550, BOARD: t186ref, EABI: aarch64, DATE: Wed May 19 18:16:00 UTC 2021

that nvoverlaysink correctly uses properties on first run, but if the pipeline is stopped and restarted the properties seem ignored:

#!/usr/bin/env python

import signal
import sys
import time
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

# Signal handler for stopping pipeline before destruction, so that Argus keeps ok.
def signal_handler(sig, frame):
    p.set_state(Gst.State.NULL)
    sys.exit(0)

# Initialize gstreamer
GObject.threads_init()
Gst.init(None)

# Define pipeline 
gst_str = "nvarguscamerasrc ! video/x-raw(memory:NVMM),format=NV12,width=3264,height=2464,framerate=21/1,pixel-aspect-ratio=1/1 \
         ! nvvidconv ! video/x-raw(memory:NVMM),width=480,height=380,pixel-aspect-ratio=1/1 \
         ! nvoverlaysink overlay-x=0 overlay-y=360 overlay-w=480 overlay-h=380 "

# Create the pipeline
p = Gst.parse_launch (gst_str)

# Register signal handler for proper termination if receiving SIGINT such as Ctrl-C
signal.signal(signal.SIGINT, signal_handler)

# Start the pipeline
p.set_state(Gst.State.READY)
p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.PLAYING)

# Run for 5s 
time.sleep(5)

# Done. Stop the pipeline before restarting.
#p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.NULL)
#time.sleep(5)
p.set_state(Gst.State.READY)
p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.PLAYING)

# Run for 5s 
time.sleep(5)

# Done. Stop the pipeline before clean up on exit.
p.set_state(Gst.State.NULL)
exit(0)

On initial pipeline run, the overlay is correct size and position, but after restarting the pipeline it gets to full resized.
Is there any workaround or patch ?

Hi Honey Patouceul,
Please check if it works by calling set_property() before changing to PLAYING state:

... ! nvoverlaysink name=myoverlay
overlay = pipeline.get_by_name("myoverlay")
overlay.set_property("overlay-x", 0)
overlay.set_property("overlay-y", 360)
overlay.set_property("overlay-w", 480)
overlay.set_property("overlay-h", 380)

Thanks Dane for the suggestion, but this doesn’t help.
The parameters are only applied in first run, ignored in next runs:

#!/usr/bin/env python

import signal
import sys
import time
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

# Signal handler for stopping pipeline before destruction, so that Argus keeps ok.
def signal_handler(sig, frame):
    p.set_state(Gst.State.NULL)
    sys.exit(0)

# Initialize gstreamer
GObject.threads_init()
Gst.init(None)

# Define pipeline 
gst_str = "nvarguscamerasrc ! video/x-raw(memory:NVMM),format=NV12,width=3264,height=2464,framerate=21/1,pixel-aspect-ratio=1/1 \
         ! nvvidconv \
         ! video/x-raw(memory:NVMM),width=480,height=380,pixel-aspect-ratio=1/1 \
         ! nvoverlaysink name=myoverlay "

# Create the pipeline
p = Gst.parse_launch (gst_str)

# Register signal handler for proper termination if receiving SIGINT such as Ctrl-C
signal.signal(signal.SIGINT, signal_handler)

overlay = p.get_by_name("myoverlay")
overlay.set_property("overlay-x", 0)
overlay.set_property("overlay-y", 360)
overlay.set_property("overlay-w", 480)
overlay.set_property("overlay-h", 380)

# Start the pipeline
p.set_state(Gst.State.READY)
p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.PLAYING)

# Run for 5s 
time.sleep(5)

# Done. Stop the pipeline before restarting.
#p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.NULL)
#time.sleep(5)

#overlay = p.get_by_name("myoverlay")
overlay.set_property("overlay-x", 0)
overlay.set_property("overlay-y", 360)
overlay.set_property("overlay-w", 480)
overlay.set_property("overlay-h", 380)

p.set_state(Gst.State.READY)
p.set_state(Gst.State.PAUSED)
p.set_state(Gst.State.PLAYING)

# Run for 5s 
time.sleep(5)

# Done. Stop the pipeline before clean up on exit.
p.set_state(Gst.State.NULL)
exit(0)

hi Honey Patouceul,
Please try

#!/usr/bin/env python3

import gi
import time
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GLib

pipeline = None
bus = None
message = None

# initialize GStreamer
Gst.init(None)

for i in range(1, 100):
    print("loop =",i," ")
    # build the pipeline
    pipeline = Gst.parse_launch(
            "videotestsrc ! video/x-raw,width=1920,height=1080 ! nvvidconv ! video/x-raw(memory:NVMM),width=480,height=380,pixel-aspect-ratio=1/1 ! nvoverlaysink overlay-x=0 overlay-y=360 overlay-w=480 overlay-h=380 "
    )

    # start playing
    print("Switch to PLAYING state")
    pipeline.set_state(Gst.State.PLAYING)

    time.sleep(5)
    print("Send EoS")
    Gst.Element.send_event(pipeline, Gst.Event.new_eos())
    # wait until EOS or error
    bus = pipeline.get_bus()
    msg = bus.timed_pop_filtered(
        Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS)

    # free resources
    print("Switch to NULL state")
    pipeline.set_state(Gst.State.NULL)
    time.sleep(1)

The working case is to re-initialize the pipeline. In C code, after switching to NULL state, we will call

    gst_object_unref(GST_OBJECT(gst_pipeline));

But the function call seems not required in python code. If we run the sample and check memory through top, we don’t observe memory increase. So it should be fine to re-initialize the pipeline. Please give it a try.

Thanks Dane for the workaround, of course if relaunching a brand new pipeline it would again again consider parameters for first run.
But (even if not destroying) relaunching pipeline would require some delay.

I think that the expected behaviour would be not to ignore properties when restarting pipeline.
Hope this can be fixed in a next release.

Hi,
Please try to reset the properites and then re-configure it:

overlay = pipeline.get_by_name("myoverlay")

overlay.set_property("overlay-x", 0)
overlay.set_property("overlay-y", 0)
overlay.set_property("overlay-w", 0)
overlay.set_property("overlay-h", 0)

overlay.set_property("overlay-x", 0)
overlay.set_property("overlay-y", 360)
overlay.set_property("overlay-w", 480)
overlay.set_property("overlay-h", 380)

Thanks Dane, this workaround works.

1 Like