How to make Element Factory in python gi.repository.Gst?

Hi
I have try this in shell and it work:

gst-launch-1.0 \
  rtspsrc location=rtsp://admin:123456@192.168.0.102:7070/stream1 latency=1 ! \ 
  queue ! rtph264depay ! h264parse ! \
  avdec_h264 ! videoconvert ! videoscale ! \ 
  video/x-raw,width=640,height=480 ! autovideosink

And now I am trying to do it in python, prase_launch work well !

pipeline = Gst.parse_launch("""
    rtspsrc location=rtspsrc location=rtsp://admin:123456@192.168.0.102:7070/stream1 latency=5 ! 
    queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! 
    video/x-raw,width=640,height=480 ! 
    autovideosink
    """)

But when I try Element Factory , it fail, no window show up
Did I do somthing wrong?

# Create pipe and element
pipeline = Gst.Pipeline()
rtspsrc = Gst.ElementFactory.make("rtspsrc", "source")
queue = Gst.ElementFactory.make("queue", "queue")
rtph264depay = Gst.ElementFactory.make("rtph264depay", "depay")
h264parse = Gst.ElementFactory.make("h264parse", "parse")
avdec_h264 = Gst.ElementFactory.make("avdec_h264", "decoder")
videoconvert = Gst.ElementFactory.make("videoconvert", "convert")
videoscale = Gst.ElementFactory.make("videoscale", "scale")
capsfilter = Gst.ElementFactory.make("capsfilter", "capsfilter")
autovideosink = Gst.ElementFactory.make("autovideosink", "sink")

# Add elements to pipe
pipeline.add(rtspsrc)
pipeline.add(queue)
pipeline.add(rtph264depay)
pipeline.add(h264parse)
pipeline.add(avdec_h264)
pipeline.add(videoconvert)
pipeline.add(videoscale)
pipeline.add(capsfilter)
pipeline.add(autovideosink)

# Set property
rtspsrc.set_property("location", CAM1_P)
rtspsrc.set_property("latency", 1)

caps_str = "video/x-raw,width=640,height=480"
caps = Gst.Caps.from_string(caps_str)
capsfilter.set_property("caps", caps)
# videoscale.set_caps(Gst.Caps.from_string())

# # Link the pipe
rtspsrc.link(queue)
queue.link(rtph264depay)
rtph264depay.link(h264parse)
h264parse.link(avdec_h264)
avdec_h264.link(videoconvert)
videoconvert.link(videoscale)
videoscale.link(capsfilter)
capsfilter.link(autovideosink)

This work, but now the code is ugly :cry:

I try to re write my code as

rtph264depay = None
LOCK = True
def on_rtspsrc_pad_added(rtspsrc, pad, *user_data):
    global 
    rtph264depay = Gst.ElementFactory.make("rtph264depay", "depay")
    pipeline.add(rtph264depay)
    rtspsrc.link(rtph264depay)
    LOCK = False

rtspsrc.connect("pad-added", on_rtspsrc_pad_added)

while LOCK:
    # wait pad
    time.sleep(0.1)

# Link and set other pipe and elements

You don’t need the LOCK thing there.

You can just add the rtph264depay to the pipeline from the start, and link it to the next element.

The only thing you can’t do at the beginning is link rtspsrc and rtph264depay, because rtspsrc has dynamic pads.

So in the rtspsrc pad-added callback you then just link the new pad to the rtph264depay’s sink pad, and that’s it.

Hi tpm,
I have try re-write my code to this.

import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, Gtk, GLib
import sys
import os
import time

os.environ["GST_DEBUG"] = "*:1"

# gst-launch-1.0 
#   rtspsrc location=rtsp://admin:123456@192.168.0.102:7070/stream1 latency=1 ! 
#   queue ! rtph264depay ! h264parse ! 
#   avdec_h264 ! videoconvert ! videoscale ! 
#   video/x-raw,width=640,height=480 ! autovideosink

# # Create a GStreamer pipeline
# pipeline = Gst.parse_launch("""
#     rtspsrc location={} latency=5 rfc7273-sync=true ! 
#     queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! 
#     video/x-raw,width=640,height=480 ! 
#     autovideosink
#     """.format(CAM1_P))
CAM1_P = "rtsp://admin:123456@192.168.0.100:7070/stream1"

Gst.init(sys.argv)

# Create pipe and element
pipeline = Gst.Pipeline()
rtspsrc = Gst.ElementFactory.make("rtspsrc", "source")
queue = Gst.ElementFactory.make("queue", "queue")
rtph264depay = Gst.ElementFactory.make("rtph264depay", "depay")
h264parse = Gst.ElementFactory.make("h264parse", "parse")
avdec_h264 = Gst.ElementFactory.make("avdec_h264", "decoder")
videoconvert = Gst.ElementFactory.make("videoconvert", "convert")
videoscale = Gst.ElementFactory.make("videoscale", "scale")
capsfilter = Gst.ElementFactory.make("capsfilter", "capsfilter")
autovideosink = Gst.ElementFactory.make("autovideosink", "sink")

# Add elements to pipe
pipeline.add(rtspsrc)
pipeline.add(queue)
pipeline.add(rtph264depay)
pipeline.add(h264parse)
pipeline.add(avdec_h264)
pipeline.add(videoconvert)
pipeline.add(videoscale)
pipeline.add(capsfilter)
pipeline.add(autovideosink)

# Set property
rtspsrc.set_property("location", CAM1_P)
rtspsrc.set_property("latency", 5)
rtspsrc.set_property("retry", 5)

caps_str = "video/x-raw,width=640,height=480"
caps = Gst.Caps.from_string(caps_str)
capsfilter.set_property("caps", caps)


# Link the pipe
rtspsrc.link(queue)
# do it in on_rtspsrc_padd_add()
# queue.link(rtph264depay)
# rtph264depay.link(h264parse)
h264parse.link(avdec_h264)
avdec_h264.link(videoconvert)
videoconvert.link(videoscale)
# videoscale.link(autovideosink)
videoscale.link(capsfilter)
capsfilter.link(autovideosink)

def on_rtspsrc_padd_add(rtspsrc, pad, *user_data):
    queue.link(rtph264depay)
    rtph264depay.link(h264parse)
    
rtspsrc.connect("pad-added", on_rtspsrc_padd_add)

loop = GLib.MainLoop()
pipeline.set_state(Gst.State.PLAYING)

try:
    loop.run()
except:
    loop.quit()

pipeline.set_state(Gst.State.NULL)

But not working :cry: ( , no window show up.

Oops…
I found the problem in on_rtspsrc_padd_add()
Should link source to queue.
And now it work.

def on_rtspsrc_padd_add(rtspsrc, pad, *user_data):
    rtspsrc.link(queue)