简体   繁体   中英

Is there a guide for converting a gstreamer pipeline to python code?

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM