Reputation: 1
I am trying to implement a simple gstreamer
pipeline that works okay through terminal command (gst-launch-1.0 filesrc location=sample.264 ! h264parse ! decodebin ! videoconvert ! autovideosink
) using python. Here is my complete code:
import sys
import platform
import configparser
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, GLib
def bus_call(bus, message, loop):
t = message.type
if t == Gst.MessageType.EOS:
sys.stdout.write("End-of-stream\n")
loop.quit()
elif t==Gst.MessageType.WARNING:
err, debug = message.parse_warning()
sys.stderr.write("Warning: %s: %s\n" % (err, debug))
elif t == Gst.MessageType.ERROR:
err, debug = message.parse_error()
sys.stderr.write("Error: %s: %s\n" % (err, debug))
loop.quit()
return True
def main(args):
if len(args) != 2:
sys.stderr.write("usage: %s <media file or uri>\n" % args[0])
sys.exit(1)
GObject.threads_init()
Gst.init(None)
print("Creating Pipeline \n ")
pipeline = Gst.Pipeline()
if not pipeline:
sys.stderr.write(" Unable to create Pipeline \n")
print("Creating Source \n ")
source = Gst.ElementFactory.make("filesrc", "file-source")
if not source:
sys.stderr.write(" Unable to create Source \n")
print("Creating H264Parser \n")
h264parser = Gst.ElementFactory.make("h264parse", "h264-parser")
if not h264parser:
sys.stderr.write(" Unable to create h264 parser \n")
print("Creating Decoder \n ")
decoder = Gst.ElementFactory.make("decodebin", "decode")
if not decoder:
sys.stderr.write(" Unable to create Decode \n")
print("Creating Video Converter \n ")
converter = Gst.ElementFactory.make("videoconvert", "converter")
if not source:
sys.stderr.write(" Unable to create Video Converter \n")
print("Creating Sink \n ")
sink = Gst.ElementFactory.make("autovideosink", "video-sink")
if not source:
sys.stderr.write(" Unable to create Sink \n")
print("Playing file %s " %args[1])
source.set_property('location', args[1])
print("Adding elements to Pipeline \n")
pipeline.add(source)
pipeline.add(h264parser)
pipeline.add(decoder)
pipeline.add(converter)
pipeline.add(sink)
print("Linking elements in the Pipeline \n")
source.link(h264parser)
h264parser.link(decoder)
decoder.link(converter)
converter.link(sink)
loop = GLib.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect ("message", bus_call, loop)
print("Starting pipeline \n")
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except:
pass
pipeline.set_state(Gst.State.NULL)
if __name__ == '__main__':
sys.exit(main(sys.argv))
When I run this script, the terminal shows an error after starting the pipeline:
Error: gst-stream-error-quark: Internal data stream error. (1): gstbaseparse.c(3634): gst_base_parse_loop (): /GstPipeline:pipeline0/GstH264Parse:h264-parser:
streaming stopped, reason not-linked (-1)
Here is the complete terminal output:
sudo python3 pipe.py sample.264
Creating Pipeline
Creating Source
Creating H264Parser
Creating Decoder
Creating Video Converter
Creating Sink
Playing file sample.264
Adding elements to Pipeline
Linking elements in the Pipeline
Starting pipeline
Error: gst-stream-error-quark: Internal data stream error. (1): gstbaseparse.c(3634): gst_base_parse_loop (): /GstPipeline:pipeline0/GstH264Parse:h264-parser:
streaming stopped, reason not-linked (-1)
Is there a way to solve this?
Upvotes: 0
Views: 5674
Reputation: 7373
You can make your life a lot easier when using convenience function like gst_parse_launch()
. This will construct pipelines from the same syntax you give to gst-launch-1.0
.
In python and your example something along this:
pipeline = Gst.parse_launch("filesrc location=sample.264 ! h264parse ! decodebin ! videoconvert ! autovideosink")
You can set bus callbacks on that pipeline and set it to PLAYING etc like you did in your example.
Some explanation on your original code: You use the decodebin
element. That one will only expose pads once the pipeline is running. So you cannot link it to anything before that. That is something that has to be done manually by hooking into it's callbacks.
For further reading head on to the dynamic pipeline example:
https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c
gst-launch-1.0
as well as gst_parse_launch()
create this logic automatically for you internally.
Upvotes: 3