GStreamer1.0

Differences between revisions 34 and 35
Revision 34 as of 2012-06-21 18:26:28
Size: 10029
Editor: 173-14-15-225-Colorado
Comment:
Revision 35 as of 2012-06-21 18:32:49
Size: 10110
Editor: 173-14-15-225-Colorado
Comment:
Deletions are marked like this. Additions are marked like this.
Line 79: Line 79:
Then when you port to Python3, replace '''python-gi''' with '''python3-gi'''.

Novacut Wiki Home > GStreamer 1.0

GStreamer 1.0 packages are now available in Ubuntu Quantal. For Ubuntu Precise (12.04 LTS) users, there are back-ported packages available in the GStreamer developers PPA.

Note that GnonLin and GES packages are not yet available for GStreamer 1.0.

Although GStreamer 1.0 is not backward compatible with the GStreamer 0.10 series, it is parallel-installable. So you can safely install GStreamer 1.0 without effect on the many applications using GStreamer 0.10.

Adding PPA for Ubuntu Precise

To use the back-ported packages for Ubuntu 12.04 LTS, add the GStreamer developers PPA like this:

  • sudo apt-add-repository ppa:gstreamer-developers/ppa
    sudo apt-get update

Installing GStreamer 1.0 packages

This should give you all the packages you likely want:

  • sudo apt-get install gstreamer1.0-tools \
        gir1.2-gstreamer-1.0 \
        gir1.2-gst-plugins-base-1.0 \
        gstreamer1.0-plugins-good \
        gstreamer1.0-plugins-ugly \
        gstreamer1.0-plugins-bad \
        gstreamer1.0-libav

Using GStreamer 1.0 from Python

You can use GStreamer 1.0 from Python (2 or 3) using PyGI like this:

  • >>> import gi
    >>> gi.require_version('Gst', '1.0')
    >>> from gi.repository import Gst
    >>> Gst.version()
    (1, 0, 0, 0)

Although currently the default will be Gst 1.0 if available, it's still a good idea to gi.require_version('Gst', '1.0') so that the code will clearly fail if Gst 1.0 isn't available.

The biggest change for Python users will be using the introspected API rather than the static python-gst bindings. However, there are also API changes in the GStreamer itself, although these changes are generally more subtle.

Python Porting Guide

Here's a quick guide to porting your PyGST app to GStreamer1.0 + PyGI. Some things are missing, but it should get you most of the way there.

Also see porting-to-0.11.txt. Although from a C perspective, you can usually figure out the equivalent Python API fairly easily once you get the hang of PyGI.

Note that although you can sort-of use GStreamer0.10 with PyGI, key functionality is fundamentally broken and wont ever be fixed in GStreamer0.10 (because it would require API breakage). It's unproductive to try and first port to PyGI, then to GStreamer1.0. You need to do both in one move.

If your PyGST app is also a PyGTK app (fairly likely), this means you need to make the jump to PyGI + Gtk3 at the same time. You cannot use PyGI and any of the static python-gobject based bindings together in the same process.

You just have to jump into the deep end and go for it. If you have extensive unit tests, pat yourself on the back, because you'll have a much easier time.

On the upside, once you port to PyGI, it's generally very easy to port to Python3. And you should, all the cool kids are doing it.

debian/control

You'll have to update your debian/control, of course. So replace:

  • Depends: python-gst0.10

With:

  • Depends: python-gi, gir1.2-gstreamer-1.0, gir1.2-gst-plugins-base-1.0

Then when you port to Python3, replace python-gi with python3-gi.

Imports

Replace:

  • import gobject
    import gst

With:

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

After that a bit of search and replace (used with care) can help. Basically:

  • gobject.* => GObject.*
    gst.* => Gst.*

Gst.init()

You should call GObject.threads_init() in your module-scope, right after your imports. Unlike the static bindings, you also need to call Gst.init(). So replace:

  • gobject.threads_init()

With:

  • GObject.threads_init()
    Gst.init(None)

element_factory_make()

Replace:

  • src = gst.element_factory_make('filesrc')

With:

  • src = Gst.ElementFactory.make('filesrc', None)

There is no equivalent to gst.element_link_many(), so replace:

  • gst.element_link_many(one, two, three)

With:

  • one.link(two)
    two.link(three)

Pipeline.add(one, two)

Bin.add() can't be overloaded to add multiple elements at once. So replace:

  • pipeline = gst.Pipeline()
    pipeline.add(one, two)

With:

  • pipeline = Gst.Pipeline()
    pipeline.add(one)
    pipeline.add(two)

one.link(two, mycaps)

Replace:

  • one.link(two, mycaps)

With:

  • one.link_filtered(two, mycaps)

STATE_PLAYING

Replace:

  • pipeline.set_state(gst.STATE_PLAYING)

With:

  • pipeline.set_state(Gst.State.PLAYING)

And so on. Some search-and-replace is helpful here, basically:

  • gst.STATE_* => Gst.State.*

GhostPad

You've got to use GhostPad.new(). So replace:

  • ghost = gst.GhostPad('sink', mysinkpad)

With:

  • ghost = Gst.GhostPad.new('sink', mysinkpad)

Pad.get_caps()

In callbacks for "pad-added" events and similar, it's common to use the string representation of the pad caps as a way to decide whether to link a pad and what to link the pad to.

You need to use Pad.query_caps() instead of Pad.get_caps(), and the returned object is no longer array-like. So in general replace this pattern:

  • def on_pad_added(element, pad):
        string = pad.get_caps()[0].get_name()
        if string.startswith('audio/'):
            <link to some audio elements>

With this:

  • def on_pad_added(element, pad):
        string = pad.query_caps(None).to_string()
        if string.startswith('audio/'):
            <link to some audio elements>

Element.get_pad()

Element.get_pad() has been renamed Element.get_static_pad(). So replace something like this:

  • src = gst.element_factory_make('filesink')
    pad = src.get_pad('sink')

With this:

  • src = Gst.ElementFactory.make('filesink', None)
    pad = src.get_static_pad('sink')

Pad.get_negotiated_caps()

Pad.get_negotiated_caps() has been renamed Pad.get_current_caps(), so replace:

  • caps = pad.get_negotiated_caps()

With:

  • caps = pad.get_current_caps()

caps[0]

Caps objects are not array-like from PyGI, so replace:

  • cap = caps[0]

With:

  • cap = caps.get_structure(0)

caps[0]['foo']

Individual capability structures are not dictionary-like objects from PyGI, so you need to use type-appropriate accessor methods instead. For example, replace this:

  • framerate = caps[0]['framerate']
    width = caps[0]['width']
    height = caps[0]['height']

With:

  • (success, num, denom) = caps.get_structure(0).get_fraction('framerate')
    (success, width) = caps.get_structure(0).get_int('width')
    (success, height) = caps.get_structure(0).get_int('height')

query_new_duration(), FORMAT_TIME

Replace:

  • query = gst.query_new_duration(Gst.FORMAT_TIME)

With:

  • query = Gst.Query.new_duration(Gst.Format.TIME)

audio/x-raw, video/x-raw

"audio/x-raw-int" and "audio/x-raw-float" have been condensed into a unified "audio/x-raw" with a flexible format description.

Likewise, "video/x-raw-yuv" and "video/x-raw-rgb" have been condensed into a unified "video/x-raw" with a flexible format description.

This is much nicer because in GStreamer 0.10 certain element details were leaked that really shouldn't have been. For example, if you wanted filter caps to force a certain sample-rate, you previously needed to know whether, say, an audio encoder took audio/x-raw-int or audio/x-raw-float.

So now you can replace say:

  • caps = gst.caps_from_string('audio/x-raw-float, rate=(int)44100')

With:

  • caps = Gst.caps_from_string('audio/x-raw, rate=(int)44100')

As you're only interested in specifying the rate anyway, it's much nicer to be truly abstracted from the format details.

decodebin2

The "decodebin2" element has been renamed to "decodebin", and the old "decodebin" element has been removed.

playbin2

The "playbin2" element has been renamed to "playbin", and the old "playbin" element has been removed.

ffmpegcolorspace

The "ffmpegcolorspace" element has been replaced with the new "videoconvert" element.

ffmpeg => libav

All the major distros now ship the libav fork of ffmpeg (and current GStreamer 0.10 packages build against libav, not ffmpeg). GStreamer 1.0 was an opportunity to do some renaming to reflect this change.

gstreamer1.0-libav is the equivalent of the the gstreamer0.10-ffmpeg Debian package.

Additionally, the GStreamer elements have been renamed. For example, in 1.0 use avdec_h264 instead of ffdec_h264. Basically some search and replace:

  • ffdec_* => avdec_*
    ffenc_* => avenc_*
    ffmux_* => avmux_*
    ffdemux_* => avdemux_*

To see all the elements shipped in the gstreamer1.0-libav package, run:

  • gst-inspect-1.0 libav

The equivalent command for gstreamer0.10-ffmpeg is:

  • gst-inspect-0.10 ffmpeg

gnlfilesource

The "gnlfilesource" element has been removed, so now use the "gnlurisource" element instead.

Replace:

  • src = gst.element_factory_make('gnlfilesource')
    src.set_property('location', '/my/cool/video')

With:

  • src = Gst.ElementFactory.make('gnlurisource')
    src.set_property('uri', 'file:///my/cool/video')

Novacut/GStreamer1.0 (last edited 2014-03-14 20:16:15 by 173-14-15-225-Colorado)