Gstreamer 自动插入:在 "have-type" 上创建多路分解

Gstreamer autoplugging: create demux on "have-type"

我正在尝试使用 typefind 元素在 运行 时选择正确的多路分解器类型。如果我在播放前创建解复用器并在收到 "have-type" 信号后 link 它,一切正常。例如:

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

def on_message(bus, message, loop):
    mtype = message.type

    if mtype == Gst.MessageType.EOS:
        print("End of stream")
        loop.quit()

    return True


n = 0
def new_sample(sink, data):
    global n
    n += 1
    #print('new-sample')
    sample = sink.emit('pull-sample')
    return Gst.FlowReturn.OK


Gst.init(None)

loop = GObject.MainLoop()

pipeline = Gst.Pipeline()
src = Gst.ElementFactory.make('splitfilesrc')
typefind = Gst.ElementFactory.make('typefind')
demux = Gst.ElementFactory.make('avidemux')
sink = Gst.ElementFactory.make('appsink')

src.set_property('location', sys.argv[1])

pipeline.add(src)
pipeline.add(typefind)
pipeline.add(demux)
pipeline.add(sink)

if not src.link(typefind):
    print('Could not link src to typefind.')
    exit(1)

def demux_pad_added(element, pad):
    stream = pad.query_caps(None).to_string()
    print('Found stream: {}'.format(stream))
    result = pad.link(sink.get_static_pad('sink'))
    if result != Gst.PadLinkReturn.OK:
        print()
        print('Could not link demux to sink.')
        loop.quit()

sink.set_property('emit-signals', True)
sink.set_property('sync', False)
sink.connect('new-sample', new_sample, None)

def have_type(typefind, probability, caps):
    print('have-type:', caps.to_string())
    demux.connect('pad-added', demux_pad_added)
    if not typefind.link(demux):
        print('Could not link typefind to demux.')
        exit(1)
typefind.connect('have-type', have_type)

bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', on_message, loop)

pipeline.set_state(Gst.State.PLAYING)
try:
    loop.run()
except KeyboardInterrupt:
    print()
pipeline.set_state(Gst.State.NULL)
print('total:', n)

如果我 运行 这样我会得到类似的东西:

$ python foo.py foo.avi
have-type: video/x-msvideo
Found stream: video/x-h264, variant=(string)itu, framerate=(fraction)50/1, max-input-size=(int)1048576, width=(int)1728, height=(int)3072, stream-format=(string)byte-stream,
alignment=(string)au
^C
total: 12144

现在,如果我在 "have-type" 回调中移动 demux 创建:

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

def on_message(bus, message, loop):
    mtype = message.type

    if mtype == Gst.MessageType.EOS:
        print("End of stream")
        loop.quit()

    return True


n = 0
def new_sample(sink, data):
    global n
    n += 1
    #print('new-sample')
    sample = sink.emit('pull-sample')
    return Gst.FlowReturn.OK


Gst.init(None)

loop = GObject.MainLoop()

pipeline = Gst.Pipeline()
src = Gst.ElementFactory.make('splitfilesrc')
typefind = Gst.ElementFactory.make('typefind')
#demux = Gst.ElementFactory.make('avidemux')
sink = Gst.ElementFactory.make('appsink')

src.set_property('location', sys.argv[1])

pipeline.add(src)
pipeline.add(typefind)
#pipeline.add(demux)
pipeline.add(sink)

if not src.link(typefind):
    print('Could not link src to typefind.')
    exit(1)

def demux_pad_added(element, pad):
    stream = pad.query_caps(None).to_string()
    print('Found stream: {}'.format(stream))
    result = pad.link(sink.get_static_pad('sink'))
    if result != Gst.PadLinkReturn.OK:
        print()
        print('Could not link demux to sink.')
        loop.quit()

sink.set_property('emit-signals', True)
sink.set_property('sync', False)
sink.connect('new-sample', new_sample, None)

def have_type(typefind, probability, caps):
    print('have-type:', caps.to_string())
    demux = Gst.ElementFactory.make('avidemux')
    pipeline.add(demux)
    demux.connect('pad-added', demux_pad_added)
    if not typefind.link(demux):
        print('Could not link typefind to demux.')
        exit(1)
typefind.connect('have-type', have_type)

bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', on_message, loop)

pipeline.set_state(Gst.State.PLAYING)
try:
    loop.run()
except KeyboardInterrupt:
    print()
pipeline.set_state(Gst.State.NULL)
print('total:', n)

请注意,只有 demux = ...pipeline.add(demux) 两行已移至回调中,但此管道似乎没有执行任何操作:

$ python foo.py foo.avi
have-type: video/x-msvideo
^C
total: 0

我可能可以事先创建所有可能的解复用器,link 我想在回调中创建一个解复用器,但我想知道为什么这不起作用,我是否可以让它像这样工作?

这里有小细节。由于您将解复用器添加到管道的时间较晚,它仍处于 NULL 状态,因为它没有从管道接收到 PLAYING 的状态更改。它需要处于 PAUSED/PLAYING 状态才能真正执行任何操作。

如果我没记错的话,如果你修改你的代码让你的解复用器在连接后进入 PLAYING 状态,它应该可以工作..:[=​​12=]

    [..]
    demux = Gst.ElementFactory.make('avidemux')
    pipeline.add(demux)
    demux.connect('pad-added', demux_pad_added)
    if not typefind.link(demux):
        print('Could not link typefind to demux.')
        exit(1)
    demux.set_state(Gst.State.PLAYING)
typefind.connect('have-type', have_type)
[..]