2020年9月21日 星期一

GStreamer(Gst) - play wav file

test.py  (use multiprocessing to avoid memory leak/growth)
#!/usr/bin/env python

import tracemalloc
import weakref
import gc
import time
import signal
import sys, os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
from memory_profiler import profile
from multiprocessing import Process
  
class GTK_Main(object):

    @profile(precision=8)
    def __init__(self):
        self.player = Gst.Pipeline.new("player")
        source = Gst.ElementFactory.make("filesrc", "file-source")
        decoder = Gst.ElementFactory.make("wavparse", "wav-decoder")
        conv = Gst.ElementFactory.make("audioconvert", "converter")
        sink = Gst.ElementFactory.make("autoaudiosink", "audio-output")
        vol = Gst.ElementFactory.make("volume", "volume")
  
        self.player.add(source)
        self.player.add(decoder)
        self.player.add(conv)
        self.player.add(sink)
        self.player.add(vol)
        source.link(decoder)
        decoder.link(conv)
        conv.link(sink)
        vol.link(sink)

    def __del__(self):
        print("...delete...")
        

    @profile(precision=8)
    def start_stop(self, flag):
        if ( flag ):
            #filepath = self.entry.get_text().strip()
            filepath = "hello_world.wav"
            if os.path.isfile(filepath):
                filepath = os.path.realpath(filepath)
                #self.player.get_by_name("volume").set_property("volume", 0.1)  not work
                self.player.get_by_name("file-source").set_property("location", filepath)
                ###tracemalloc.start(3)###
                #// Wait until error or EOS:
                play = self.player.set_state(Gst.State.PLAYING)             
                bus = self.player.get_bus()
                bus.add_signal_watch()
                bus.connect("message", self.on_message)
                msg = bus.timed_pop_filtered (Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS);
                play = self.player.set_state(Gst.State.NULL)
                ###snap = tracemalloc.take_snapshot()###
                ###top_stats = snap.statistics('traceback')###
                ###stats = top_stats[0]###
                ###print("nice={}".format(stats))###
                ###for line in stats.traceback.format():###
                ###    print("nice2={}".format(line))###
                print("1. Refcnt of msg={}, play={}".format(sys.getrefcount(msg), sys.getrefcount(play)))
                gc.collect()
            else:
                play = self.player.set_state(Gst.State.NULL)
                play = None
                gc.collect()



    @profile(precision=8)
    def signal_handler(sig, frame):
        self.player.set_state(Gst.State.NULL)
        sys.exit(0)

    @profile(precision=8)
    def on_message(self, bus, message):
        t = message.type
        if t == Gst.MessageType.EOS:
            self.player.set_state(Gst.State.NULL)
        elif t == Gst.MessageType.ERROR:
            self.player.set_state(Gst.State.NULL)
            err, debug = message.parse_error()
            print ("Error: %s" % err, debug)


@profile(precision=8)
def main():
    Gst.init(None)
    GObject.threads_init()
    gtk=GTK_Main()
    signal.signal(signal.SIGINT, gtk.signal_handler)
    signal.signal(signal.SIGTERM, gtk.signal_handler)
    signal.signal(signal.SIGQUIT, gtk.signal_handler)
    while True:
          p=Process(target=gtk.start_stop, args=(int(1),))
          p.start()
          p.join()
          p=None
          target=None
          args=None
          gc.collect()

if __name__ == '__main__':
    main()


ref:
1. Python GStreamer Tutorial
2. Here
3. more example: gkralik/python-gst-tutorial

沒有留言:

張貼留言