简体   繁体   English

动态 GStreamer 管道不可查找

[英]Dynamic GStreamer pipeline not seekable

I have a simple gstreamer pipeline that plays an mp4 file and it supports seeking.我有一个简单的 gstreamer 管道,可以播放 mp4 文件并且支持搜索。 I've made another version of this pipeline, this one with the demux dynamically created using a typefind element.我制作了这个管道的另一个版本,这个版本带有使用 typefind 元素动态创建的 demux。 With this version of the pipeline, seeking doesn't seem to work.使用此版本的管道,查找似乎不起作用。 Here are the most minimal versions of these two in Python:以下是 Python 中这两个的最小版本:

Here are the pipeline diagrams:以下是管道图:

The working/seekable version:工作/可搜索版本: 工作/可搜索管道

The dynamic/non-seekable version:动态/不可搜索版本: 动态/不可搜索管道

Notice that actual playback works in both pipelines just fine.请注意,实际播放在两个管道中都可以正常工作。 Only seeking does not work in the dynamic version.在动态版本中仅搜索不起作用。 The only major difference between the two as far as I can see is that in the dynamic pipeline, the pads connecting typefind to the demux element are in pull mode while in the other they are in push mode, but I have no idea if this is relevant and if it is how to fix it.据我所知,两者之间唯一的主要区别是,在动态管道中,将 typefind 连接到 demux 元素的焊盘处于拉模式,而在另一个处于推模式,但我不知道这是否是相关,如果是如何解决它。

Another difference is that the newly created demux in the dynamic version is in the playing state while the other elements are in paused, at the seeking time.另一个区别是动态版本中新创建的 demux 处于播放状态,而其他元素处于暂停状态,在搜索时。 I've tried setting the new demux to paused state, but this does not seem to change anything.我已经尝试将新的 demux 设置为暂停状态,但这似乎并没有改变任何东西。

The most minimal version of the code I could come up with follows:我能想出的代码的最小版本如下:

Working version:工作版本:

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


def demux_pad_added(element, pad, pipeline):
    dec = pipeline.get_by_name('dec0')
    result = pad.link(dec.get_static_pad('sink'))
    if result != Gst.PadLinkReturn.OK:
        print('Could not link demux to dec.')
        exit(1)

    print('Linked demux to dec.')

    Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, 'working')

    ret = pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 1800 * Gst.SECOND)
    print('seek result:', ret)


def main():
    Gst.init(None)
    loop = GLib.MainLoop()

    pipeline = Gst.Pipeline()
    src = Gst.ElementFactory.make('filesrc', 'src0')
    typefind = Gst.ElementFactory.make('typefind', 'typefind0')
    demux = Gst.ElementFactory.make('qtdemux', 'demux0')
    dec = Gst.ElementFactory.make('libde265dec', 'dec0')
    sink = Gst.ElementFactory.make('appsink', 'sink0')

    src.set_property('location', 'foo.mp4')
    demux.connect('pad-added', demux_pad_added, pipeline)

    elements = [src, typefind, demux, dec, sink]

    for e in elements:
        pipeline.add(e)

    for i in range(0, len(elements) - 1):
        e1, e2 = elements[i], elements[i+1]
        if e1 == demux:
            continue
        if not e1.link(e2):
            print('Could not link {} to {}.'.format(e1.name, e2.name))
            exit(1)

    pipeline.set_state(Gst.State.PLAYING)
    loop.run()


if __name__ == '__main__':
    main()

The version where seek does not work:寻求不起作用的版本:

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


def demux_pad_added(element, pad, pipeline):
    dec = pipeline.get_by_name('dec0')
    result = pad.link(dec.get_static_pad('sink'))
    if result != Gst.PadLinkReturn.OK:
        print(pad.name, dec.get_static_pad('sink').name)
        print('Could not link demux to dec.')
        exit(1)

    print('Linked demux to dec.')

    Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, 'not-working')

    ret = pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 1800 * Gst.SECOND)
    print('seek result:', ret)


def typefind_have_type(typefind, probability, caps, pipeline):
    videofmt = caps.to_string()
    if ',' in videofmt:
        videofmt = videofmt.split(',')[0]

    demux_name = {
        'video/quicktime': 'qtdemux',
        'video/x-matroska': 'matroskademux',
        'video/x-msvideo': 'avidemux',
    }.get(videofmt, None)

    if not demux_name:
        print('Unknown input file format: {}'.format(videofmt))
        exit(1)

    demux = Gst.ElementFactory.make(demux_name, 'demux0')
    pipeline.add(demux)
    demux.connect('pad-added', demux_pad_added, pipeline)
    demux.set_state(Gst.State.PLAYING)

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


def main():
    Gst.init(None)
    loop = GLib.MainLoop()

    pipeline = Gst.Pipeline()
    src = Gst.ElementFactory.make('filesrc', 'src0')
    typefind = Gst.ElementFactory.make('typefind', 'typefind0')
    demux = object() # dummy
    dec = Gst.ElementFactory.make('libde265dec', 'dec0')
    sink = Gst.ElementFactory.make('appsink', 'sink0')

    src.set_property('location', 'foo.mp4')
    typefind.connect('have-type', typefind_have_type, pipeline)

    elements = [src, typefind, demux, dec, sink]

    for e in elements:
        if e != demux:
            pipeline.add(e)

    for i in range(0, len(elements) - 1):
        e1, e2 = elements[i], elements[i+1]
        if e1 == demux or e2 == demux:
            continue
        if not e1.link(e2):
            print('Could not link {} to {}.'.format(e1.name, e2.name))
            exit(1)

    pipeline.set_state(Gst.State.PLAYING)
    loop.run()


if __name__ == '__main__':
    main()

Any help would be greatly appreciated.任何帮助将不胜感激。

I managed to find the fix to this myself.我设法自己找到了解决方法。 I simply needed to move the demux.set_state(...) call to the end of the typefind callback, after linking typefind to demux.在将 typefind 链接到 demux 之后,我只需要将demux.set_state(...)调用移动到 typefind 回调的末尾。 The new typefind callback looks like this now:新的 typefind 回调现在看起来像这样:

def typefind_have_type(typefind, probability, caps, pipeline):
    videofmt = caps.to_string()
    if ',' in videofmt:
        videofmt = videofmt.split(',')[0]

    demux_name = {
        'video/quicktime': 'qtdemux',
        'video/x-matroska': 'matroskademux',
        'video/x-msvideo': 'avidemux',
    }.get(videofmt, None)

    if not demux_name:
        print('Unknown input file format: {}'.format(videofmt))
        exit(1)

    demux = Gst.ElementFactory.make(demux_name, 'demux0')
    pipeline.add(demux)
    demux.connect('pad-added', demux_pad_added, pipeline)
    #demux.set_state(Gst.State.PLAYING) # moved from here to further down

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

    demux.set_state(Gst.State.PLAYING) # <--- new location

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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