Elektito
Elektito

Reputation: 4155

Have gstreamer pipeline run at reading/decoding speed when using appsink

If I create a simple pipeline to read an mkv file into a fakesink, it will run as fast as the machine can read and process the file:

$ time gst-launch-1.0 filesrc location=bar.mkv ! matroskademux ! fakesink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Got EOS from element "pipeline0".
Execution ended after 0:00:00.000402211
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

real    0m0.020s
user    0m0.016s
sys     0m0.004s

The file in question is 5 seconds long, but this runs in a fraction of a second. Now if I want to have the same inside a program, and use an appsink instead of the fakesink, this runs at playback speed. Consider this simple Python program:

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


def on_message(bus, msg, loop):
    if msg.type == Gst.MessageType.EOS:
        print("End of stream")
        loop.quit()

    return True


def new_sample(sink, data):
    sample = sink.emit('pull-sample')
    return Gst.FlowReturn.OK


def main():
    Gst.init(None)

    loop = GObject.MainLoop()

    pipeline = Gst.Pipeline()
    src = Gst.ElementFactory.make('filesrc')
    demux = Gst.ElementFactory.make('matroskademux')
    sink = Gst.ElementFactory.make(sys.argv[1])

    src.set_property('location', 'bar.mkv')

    if sys.argv[1] == 'appsink':
        sink.set_property('emit-signals', True)
        sink.connect('new-sample', new_sample, None)

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

    src.link(demux)

    def pad_added(element, pad):
        stream = pad.query_caps(None).to_string()
        pad.link(sink.get_static_pad('sink'))
    demux.connect('pad-added', pad_added)

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

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


if __name__ == '__main__':
    main()

If I run it with a fakesink, it's still very fast:

$ time python ./foo.py fakesink
End of stream

real    0m0.095s
user    0m0.078s
sys     0m0.018s

But if I use the appsink, it takes just over 5 seconds:

$ time python ./foo.py appsink
End of stream

real    0m5.068s
user    0m0.099s
sys     0m0.014s

which shows gstreamer is synchronizing the frames so they run at the framerate specified in the file. Can we get the fakesink behavior with appsink?

Upvotes: 2

Views: 1731

Answers (1)

Florian Zwoch
Florian Zwoch

Reputation: 7383

This behavior is controlled via the the sink's sync property. By default the fakesink has this set to false. Set this property to true to have the same behavior as the appsink.

$ time gst-launch-1.0 filesrc location=bar.mkv ! matroskademux ! fakesink sync=true

Upvotes: 4

Related Questions