Building GStreamer on OSX   39 comments

Currently, the most convenient way to generate GStreamer binaries for Mac is to use the MacPorts build system. It automatically handles dependencies and patches, and it is kept well up-to-date. However, the main disadvantage of MacPorts is that the resulting GStreamer libraries are meant to be placed inside a specific location in the disk, usually /opt/local, which makes difficult to bundle them into 3rd party applications and also requires separate installs to deploy GStreamer on the end user’s machine. The reason for this problem is that the compilation process in MacPorts hard-codes the absolute paths of the dependencies into the binaries and/or libraries. The methods and scripts described below allow one to modify the GStreamer binaries built with MacPorts so they contain only relative references to dependencies, thus facilitating the integration of GStreamer with 3rd party applications on Mac OSX. These scripts and accompanying documentation are already part of the OSSBuild distribution.

The steps described here include: 1) how to compile GStreamer using MacPorts in such a way that unneeded dependencies are not included and the resulting library files (.dylib and .so) can be further processed in order to change absolute dependencies into relative dependencies, 2) using a provided python script to automatically replace the dependencies, and 3) additional processing of the library files to remove symbolic links (this last step could be useful in certain scenarios where the the symlinks make bundling GStreamer within an application harder). The end result of following these steps should be a set of GStreamer library files that can be packaged inside any 3rd party application on Mac OSX that requires GStreamer for multimedia handling.

1) Compiling GStreamer with Macports

The MacPorts build system is designed to facilitate the compilation and installation of open source software initially available for Linux/Unix systems on Mac computers. It automatically downloads the source packages, solves dependencies, applies patches, generates makefiles and compiles the binaries. The latest version of MacPorts is available for download here, and it is very well documented. Around 7300 packages are currently available through MacPorts, and among them the ones that constitute the gstreamer multimedia framework: gstreamer, gst-plugins-base, gst-plugins-good, gst-plugins-bad, gst-plugins-ugly and gst-ffmpeg.

Since we are interested in generating GStreamer libraries that can be later modified in order to change the path and name of the dependencies coded inside them, right after installing MacPorts we need to edit the file /opt/local/share/macports/Tcl/port1.0/portconfigure.tcl so the line:

default configure.ldflags {-L${prefix}/lib}

is changed into:

default configure.ldflags {“-L${prefix}/lib -Xlinker -headerpad_max_install_names”}

I originally found this trick here.

The result of this modification is that all the binaries and libraries compiled with MacPorts from now on will have enough space inside their headers so that the dependency paths buit into them can be modified into strings longer than the original. As a quick example of this, if we inspect with otool the libgstreamer-0.10.0.dylib library file that is built with MacPorts, the output should look something like this:

> otool -L /opt/local/lib/libgstreamer-0.10.0.dylib
/opt/local/lib/libgstreamer-0.10.0.dylib:
/opt/local/lib/libgstreamer-0.10.0.dylib (compatibility version 26.0.0, current version 26.0.0)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 41.0.0)
/opt/local/lib/libgobject-2.0.0.dylib (compatibility version 2401.0.0, current version 2401.1.0)
/opt/local/lib/libgthread-2.0.0.dylib (compatibility version 2401.0.0, current version 2401.1.0)
/opt/local/lib/libgmodule-2.0.0.dylib (compatibility version 2401.0.0, current version 2401.1.0)

If we wish to change the dependency /opt/local/lib/libgobject-2.0.0.dylib into /large/path/containing/the/dependencies/libgobject-2.0.0.dylib the dylib file might not have enough space reserved in its header to do so. The hack described above ensures that all the files compiled by MacPorts have the maximum possible header space for fitting larger dependency paths.

The command to actually change the path in this particular example would be:

> install_name_tool -change /opt/local/lib/libgobject-2.0.0.dylib /new/large/path/containing/the/dependencies/libgobject-2.0.0.dylib /opt/local/lib/libgstreamer-0.10.0.dylib

The use of install_name_tool will be addressed in more detail in the next section.

As mentioned earlier, another issue with the GStreamer binaries obtained with an unmodified MacPorts is that they will include large dependencies that are not used in most of the cases (like x-org). The solution is fortunately quite easy, and it consists in using a local repository of portfiles containing modified portfiles without these dependencies. The portfiles I have used to compile GStreamer myself are here, and this section in the documentation page of MacPorts explains how to setup local repositories. Once the local repository is configured, the following commands should be run in order to compile all the GStreamer modules with some useful variants enabled:

sudo port install gstreamer
sudo port install gst-plugins-base +no_x11 +no_gnome_vfs
sudo port install gst-plugins-good
sudo port install gst-plugins-bad +no_x11 +dc1394
sudo port install gst-plugins-ugly
sudo port install gst-ffmpeg

MacPorts generates 64 bits binaries when running in OSX Snow Leopard, which might not be the desired output in some cases. To set the target architecture to 32 bits, add the “build_arch i386” option in the macports.conf file, which is located by default in /opt/local/etc/macports).

Note that some parts of GStreamer give errors when compiling in OSX Snow Leopard 64 bits with target architecture set to x86 32 bits (libmodplug, libid3tag, gst-ffmpeg 1 and 2). The errors with libmodplug and libid3tag were solved by just removing these dependencies from the modified portfiles. In order to compile gst-ffmpeg I applied the following hack:

1. Start gst-ffmpeg compilation and installation by running:

> sudo port install gst-ffmpeg

2. After it exits with error, change into the <local repository>/gnome/gst-ffmpeg/work/gst-ffmpeg-0.10.10 folder
and add the following #defines:
#define HAVE_EBX_AVAILABLE 0 in gst-libs/ext/ffmpeg/config.h
(this one might exist already defining the macro as 1, in this case change the line so HAVE_EBX_AVAILABLE is defined as 0 instead).
#define HAVE_MMX 0 in gst-libs/ext/ffmpeg/libswscale/rgb2rgb_template.c
3. Finish compilation and installation by running:

> sudo make; make install

2) Setting relative dependency paths
GStreamer libraries compiled with MacPorts contain absolute paths for their dependencies and file id’s, the output of otool -L in the previous section shows this. It was also mentioned in the previous section that the install_name_tool command allows us to modify these paths. However, doing this manually would be quite time consuming, since GStreamer is composed at least of ~250 separate
.dylib and .so files. I wrote the replacepath.py script to facilitate this operation. The syntax of this script is as follows:

> replacepath.py ––old /opt/local/lib/ ––new @loader_path/ ––dir ./libs -R

where “/opt/local/lib/” is in this case the old absolute path to replace by the string “@loader_path/”. The folder to process is specified after –dir, and the -R switch enables to process the folder recursively. Relative paths inside a library file can be indicated using the @executable_path, @loader_path and @rpath tokens, which are explained in the Mac OSX reference page for dyld (under the section DYNAMIC LIBRARY LOADING) and discussed in detail in this post. In my particular case, which consisted in bundling GStreamer with the GSVideo library so it can be loaded from PDE sketches as well as from exported applications, the correct relative path
variable to use is @loader_path.

3) Eliminating symbolic links

Most, if not all, the dylib files generated by MacPorts as part of GStreamer have one or more symbolic link pointing to the actual library file. For instance:

> ls /opt/local/lib/libwavpack*dylib
-rwxr-xr-x 1 andres staff 168032 Aug 9 14:20 /opt/local/lib/libwavpack.1.1.4.dylib
lrwxr-xr-x 1 andres staff 22 Aug 9 14:20 /opt/local/lib/libwavpack.1.dylib -> libwavpack.1.1.4.dylib
lrwxr-xr-x 1 andres staff 22 Aug 9 14:20 /opt/local/lib/libwavpack.dylib -> libwavpack.1.1.4.dylib

The presence of symbolic links might complicate the use of GStreamer from 3rd party applications, so it could be useful to have a tool to remove all these symlinks while keeping the correct dependency structure of the library files. Preserving the dependencies is precisely the tricky part, since the path specification inside interconnected libraries usually refer to the name of actual library file, while some other pieces of software might attempt to load the libraries using the name of the symlinks instead. For this reason I created another post-build script, removesymlinks.py, which analyses a given folder and renames all the libraries files in it to have the name of the found symbolic link with the shortest name, and updates all the headers accordingly. An example of use would be as follows:

./removesymlinks.py ––dir gstreamer

where the only required argument is the folder containing the library files and their symlinks.

4. Concluding remarks

This post is over long and mostly a mashup of hacks and tricks I found on the Internet over the past year since started to investigate the compilation of GStreamer on OSX. Still, I hope it can be of help to other people dealing with similar issues. Suggestions and improvements for the post-build scripts described here will also be greatly appreciated.

Advertisements

Posted August 31, 2010 by ac in Programming

Tagged with , , , , , ,

39 responses to “Building GStreamer on OSX

Subscribe to comments with RSS.

  1. Pingback: GSVideo 0.7 « codeanticode

  2. I installed gstreamer on Snow Leopard in 64 bit mode. But I am missing the osxaudio/video sink plugins.

    • I was wrong. Osx sinks are available. But I get a lot of exceptions when I play around. I guess the 64 Bit Version is still unstable.

      • Yes, the sinks are available. However osxvideosrc (for video capture) seems to be missing from the 64 bits build. Were you able to compile it?

  3. There seems to be a problem with 64 bit, causing an excetion in Darwin extension .. see below.
    Anyone have an idea how to solve it?

    Caught SIGSEGV accessing address 0x77aa08
    #0 0x00007fff85d7fdce in select$DARWIN_EXTSN ()
    #1 0x00000001003497a2 in g_poll ()
    #2 0x000000010033c508 in g_main_context_iterate ()
    #3 0x000000010033c805 in g_main_loop_run ()
    #4 0x0000000100020ce1 in gst_bus_poll ()
    #5 0x0000000100005aeb in _print ()
    #6 0x0000000100006e03 in ?? ()
    #7 0x0000000100005724 in _print ()
    Spinning. Please run ‘gdb gst-launch 33476’ to continue debugging, Ctrl-C to quit, or Ctrl-\ to dump core.

  4. Roland: GStreamer via MacPorts has been working great for me until very recently (last few weeks), where using osxaudiosink will cause the crash that you’ve encountered. I’ve reverted my build back to GStreamer 0.10.29 in MacPorts – which is stable again.

    • This post was based on the 0.10.29 release of gstreamer, which seemed to work on both on 32 and 64 bits (the only issue so far was osxvideosrc missing in the 64 bits build). I haven’t tried 0.10.30 yet.

  5. It seems hard to install GStreamer. BUt thank you for the help!!

    • Yes, compiling gstreamer can be difficult, even with the help of macports. In any case, the idea of this post was to provide some useful info for other developers. My final goal here is to offer precompiled OSX binaries of gstreamer as part of the OSSBuild project. Stay tuned.

  6. I’ve put together a simple binary installer for GStreamer 0.10.29 using MacPorts. Both 32- and 64-bit builds are included within the single installer package (136 MB).

    You can download it at: http://itee.uq.edu.au/~davel/gstreamer/

    However, unlike in the above blog post, the paths are hard-coded to /System/Library/Frameworks/GStreamer.framework/Versions/… (like with the JavaVM) so it’s not suitable for embedding in your own applications.

    It’s just a temporary measure and not meant to be ‘official’. I’ve simply included two duplicate copies of MacPorts rather than a single universal binary tree, etc. Once v0.10.30 in MacPorts works reliably for me, I’ll put together another installer.

    Enjoy!

    • Awesome! Thanks! I guess anyone wanting to adapt your binaries for bundling inside apps can use the scripts I describe in the post to replace /System/Library/Frameworks/GStreamer.framework/Versions/… with @loader_path… Excellent!

      Now, these binaries are meant for Snow Leopard (32/64 bits) only?

      • Good idea for bundling inside apps.

        I specified 10.6 / Snow Leopard only because that’s the platform that I used to compile and test the installer – I don’t know if it will work on 10.5 / Leopard. I’ll give it a test tomorrow and report back.

        Btw, I’ve just added Java directions for binding gstreamer-java to the installed binaries when running on Mac OS X.

      • Great! Thanks again!

      • Regarding Leopard, I recently found out that the binaries compiled on 10.6 with the instructions I posted in the wiki, specifically in the section “Compiling on a different Platform”, seem to work fine on 10.5.

    • The osxvideosrc plugin is missing from the 64 bits libs. I had the same problem (it compiles when the target is set to 32 bits but not to 64). Do you have any idea why?

      • I had a look at the source, and it’s because osxvideosrc uses the older 32-bit Carbon QuickTime API, which has been deprecated in 64-bit mode (same reason why Adobe spent so long converting Photoshop CS5 to 64-bit). The plugin needs to be rewritten for the newer Cocoa QTKit API (which will work in 32-bit and 64-bit modes).

        I have dreams of doing this at some point, as well as adding a plugin for Apple’s Video Decode Acceleration Framework on OS X for GPU-based H.264 decoding, but don’t have the time right now.

        Btw you might be interested to know that I’ve added support for osxvideosink to gstreamer-java (noticeably improves playback performance), which I hope to be able to submit upstream soon.

      • All right, thanks for the info regarding osxvideosrc. I’m also quite busy at this time with other things, but I’m interested in looking at this later.

        A new version of gstreamer-java is being prepared right now, perhaps your improvements can go in it.

  7. Hi, I’m trying to stream audio in Mac OS X but I keep getting this error:

    gst-launch osxaudiosrc ! audioresample ! audioconvert ! alawenc ! rtppcmapay ! udpsink port=10001 host=192.168.2.10

    Setting pipeline to PAUSED …
    ERROR: Pipeline doesn’t want to pause.
    ERROR: from element /GstPipeline:pipeline0/GstUDPSink:udpsink0: Could not get/set settings from/on resource.
    Additional debug info:
    gstmultiudpsink.c(804): gst_multiudpsink_configure_client (): /GstPipeline:pipeline0/GstUDPSink:udpsink0:
    Could not set TTL socket option (22): Invalid argument
    Setting pipeline to NULL …
    Freeing pipeline …

    This works in Windows, anyone know what the problem is?

    thanks

  8. @Gank: There is a bug in the udpsink/multi udpsink code related to IPV6.

    If you are coding up your pipeline in C you can bypass this by manually creating the socket to use and using that for the sink.

    g_object_set(G_OBJECT(my_sink), “sockfd”, my_tx_socket, NULL);

  9. Is this solution possible in Gstreamer-java?

  10. First off all thank you very much for these infos!

    I’m developing a streaming application in c++ which is based on wxWidgets + GStreamer. It runs fine under Win + Lin and I would like to port it to Mac too, but I have problems to embed the video into my player window.

    As far as I understand I have to handle the “have-ns-view” message and get the “nsview” which is no problem, but

    1) how to find my player window?

    Win: HWND window = (HWND)MainFrame->EmbeddedVideoWindow->GetHandle();
    Lin: Window window = GDK_WINDOW_XWINDOW(GTK_PIZZA(MainFrame->EmbeddedVideoWindow->m_wxwindow)->bin_window);
    Mac: ???

    2) how to set it to make osxvideosink use it?

    When I use wxGTK/ximagesink instead of wxMAC/osxvideosink everything works fine, but the gui looks bad.

    Would be great if you have some tipps for using the native osxvideosink. This would make many users happy which waits a long time for an mac port of my app…

    Thanks,
    Thomas

    • Hello Thomas,

      My experience with gstreamer on OSX, besides compiling it with macports, is limited to its use through the gstreamer-java bindings. I haven’t done any work with wxWidgets + GStreamer in C/objective C/etc, so unfortunately I’m not able to provide much help here.

      BTW, did you check the Mac installer by David Liu, it might at least simplify the initial steps of setting up all the required gstreamer files.

      Andres

  11. Hi Dave,
    Thanks for putting up this page. It was really useful in getting me started on mac for gstreamer. Do you have any update on osxvideosrc?

  12. Thanks, ac. Was able to build and run qtkitvideosrc, but miovideosrc generates one frame and freezes …

  13. Is it possible for a 64-bit application to call the APIs that are implemented in 32-bit compiled Gstreamer library?

  14. I’ve had a nightmare trying to get certain parts of gstreamer working on osx. rtmpsink does not seem to be available after trying to install from brew and the packages available directly from gstreamer 1.2.1. I’m concidering compiling from source, or does anyone have a better option?

  15. Building GStreamer for Mac OS X and iOS

    http://luisbg.blogalia.com/historias/74916

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: