Where are Gstreamer bus log messages?

落花浮王杯 提交于 2020-05-16 05:53:29

问题


I am trying to stream a .mp4 to a RTSP server using Gstreamer in python

import sys
import gi

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

loop = GLib.MainLoop()
Gst.init(None)
file_path = "test.mp4"
class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
    def __init__(self):
        GstRtspServer.RTSPMediaFactory.__init__(self)

    def do_create_element(self, url):
        src_demux = f"filesrc location={file_path} ! qtdemux name=demux"
        h264_transcode = "demux.video_0"
        pipeline = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)
        print ("Element created: " + pipeline)

        self._pipeline = Gst.parse_launch(pipeline)
        def bus_handler(bus, message):
            print(message)
        self.bus = self._pipeline.get_bus()
        self.bus.connect('message', bus_handler)
        self.bus.add_signal_watch_full(1)
        return self._pipeline

class GstreamerRtspServer():
    def __init__(self):
        self.rtspServer = GstRtspServer.RTSPServer()
        factory = TestRtspMediaFactory()
        factory.set_shared(True)
        mountPoints = self.rtspServer.get_mount_points()
        self.address = '127.0.0.1' #my RPi's local IP
        self.port = '8553'
        self.rtspServer.set_address(self.address)
        self.rtspServer.set_service(self.port)
        urlstr = "/user=&password=.sdp"
        url = GstRtsp.RTSPUrl.parse(urlstr)
        mountPoints.add_factory(urlstr, factory)

        self.rtspServer.attach(None)

if __name__ == '__main__':
    s = GstreamerRtspServer()
    loop.run()

However I am trying to understand how to use Gstreamer bus to log messages like eos or errors and warnings but I don't see any, even when I send eos events and the streaming effectively stops

s.rtspServer._pipeline._end_stream_event.set()
s.rtspServer._pipeline.send_event(Gst.Event.new_eos())

Am I using it properly? If not, what can I fix to properly log bus messages?


回答1:


Following solution is based on this accepted but somehow incomplete answer.

I found out the way that does not require "manual" creation of pipeline elements but instead it keeps (in this scenario) convenient Gst.parse_launch(pipelineCmd) method and extends Gst.Bin to enable message debugging.

Here is full example source code (check out commented lines for some explanations):

#!/usr/bin/env python

import sys
import gi

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

Gst.init(None)
loop = GLib.MainLoop()

# extended Gst.Bin that overrides do_handle_message and adds debugging
class ExtendedBin(Gst.Bin):
    def do_handle_message(self,message):
        if message.type == Gst.MessageType.ERROR:
            error, debug = message.parse_error()
            print("ERROR:", message.src.get_name(), ":", error.message)
            if debug:
                print ("Debug info: " + debug)
        elif message.type == Gst.MessageType.EOS:
            print ("End of stream")
        elif message.type == Gst.MessageType.STATE_CHANGED:
            oldState, newState, pendingState = message.parse_state_changed()
            print ("State changed -> old:{}, new:{}, pending:{}".format(oldState,newState,pendingState))
        else :
            print("Some other message type: " + str(message.type))

        #call base handler to enable message propagation
        Gst.Bin.do_handle_message(self,message)

class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):

    def __init__(self):
        GstRtspServer.RTSPMediaFactory.__init__(self)

    def do_create_element(self, url):
        #set mp4 file path to filesrc's location property
        src_demux = "filesrc location=/path/to/dir/test.mp4 ! qtdemux name=demux"
        h264_transcode = "demux.video_0"
        #uncomment following line if video transcoding is necessary
        #h264_transcode = "demux.video_0 ! decodebin ! queue ! x264enc"
        pipelineCmd = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)

        self.pipeline = Gst.parse_launch(pipelineCmd)
        print ("Pipeline created: " + pipelineCmd)

        # creates extended Gst.Bin with message debugging enabled
        extendedBin = ExtendedBin("extendedBin")

        # Gst.pipeline inherits Gst.Bin and Gst.Element so following is possible
        extendedBin.add(self.pipeline)

        # creates new Pipeline and adds extended Bin to it
        self.extendedPipeline = Gst.Pipeline.new("extendedPipeline")
        self.extendedPipeline.add(extendedBin)

        return self.extendedPipeline

class GstreamerRtspServer(GstRtspServer.RTSPServer):
    def __init__(self):
        self.rtspServer = GstRtspServer.RTSPServer()
        self.factory = TestRtspMediaFactory()
        self.factory.set_shared(True)
        mountPoints = self.rtspServer.get_mount_points()
        mountPoints.add_factory("/stream", self.factory)
        self.rtspServer.attach(None)
        print ("RTSP server is ready")

if __name__ == '__main__':
    s = GstreamerRtspServer()
    loop.run()

Please note that Gst.Pipeline actually inherists/extends Gst.Bin (and Gst.Element) so it is possible (no matter how strange it sounds) to add pipeline to bin.

This little "trick" saves time for us "lazy" programmers to keep using parsing of command line syntax to create pipeline elements.

In some more complex scenarios, where parsing of command line syntax is not applicable, solution would be following:

  • create ExtendedBin,
  • "manually" create elements with Gst.ElementFactory.make method (and set necessary properties)
  • add created elements to ExtendedBean
  • link elements
  • create new pipeline and add bin to it
  • use pipeline where it is needed.


来源:https://stackoverflow.com/questions/61604103/where-are-gstreamer-bus-log-messages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!