Using Gstreamer in your Flutter project Pt.4: MacOS

Previous Tutorial Recap: We successfully ran the app on Windows. In this tutorial, we'll focus on adapting the application for macOS.

Prerequisites

Ensure you have the following foundational knowledge before proceeding:

  • Basic understanding of the C programming language.

  • Familiarity with Dart/Flutter.

  • Basic knowledge of CocoaPods.

  • Basic knowledge of GStreamer.

 

Required Tools and Software

For this tutorial, we will demonstrate the process on a Windows PC. Ensure you have the following tools and software:

  • GStreamer Libraries: Install GStreamer and its development libraries. Follow the GStreamer documentation for installation instructions. Ensure both runtime and development libraries are installed.

  • Code Editor: Any code editor will work, but we will use Visual Studio Code (VSCode).

  • Flutter: Install Flutter by following the guidelines on the official Flutter website.

  • CocoaPods: Install CocoaPods by following the guidelines on the CocoaPods website.

  • Xcode: Required for building projects on macOS. Install it through the Mac App Store.

Before proceeding, please ensure that you have Xcode, CocoaPods, and GStreamer for macOS installed.

Building the App Without Modifications

First, let's try to build the app without any modifications. Navigate to the app folder and run the build command targeting macOS with verbose output. You should see an error similar to this:

% flutter build macos -vv --debug

Running pod install...                                           2,448ms
In file included from /Users/max/Projects/fltgst/app/native_binding/macos/Classes/native_binding.c:3:
/Users/max/Projects/fltgst/app/native_binding/macos/Classes/../../src/native_binding.c:2:10: fatal error: 'gst/gst.h' file not found
#include <gst/gst.h>
         ^~~~~~~~~~~
1 error generated.
warning: Run script build phase 'Run Script' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'Flutter Assemble' from project 'Runner')
** BUILD FAILED **

Building macOS application...                                           
Build process failed

This error is expected because we need to link against the GStreamer libraries.

After installing the GStreamer libraries, they can be found at /Library/Frameworks/GStreamer.framework. Open native_binding/macos/native_binding.podspec and add header search paths and library search paths to the s.pod_target_xcconfig:

...
  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES',
   'HEADER_SEARCH_PATHS' => '"/Library/Frameworks/GStreamer.framework/Headers"',
   'LD_RUNPATH_SEARCH_PATHS' => ['"/Library/Frameworks"','"/Library/Frameworks/GStreamer.framework/Libraries"'],
  }
...

If you run the build command again, you will encounter different errors:

...
[ +202 ms] Undefined symbols for architecture x86_64:
[        ]   "_g_main_loop_is_running", referenced from:
[        ]       _run_mainloop in native_binding.o
[        ]   "_g_main_loop_new", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]   "_g_main_loop_run", referenced from:
[        ]       _run_main_loop_thread in native_binding.o
[        ]   "_g_main_loop_unref", referenced from:
[        ]       _run_mainloop in native_binding.o
[        ]       _free_resource in native_binding.o
[        ]   "_g_printerr", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]       _setup_pipeline in native_binding.o
[        ]       _start_pipeline in native_binding.o
[        ]   "_g_thread_new", referenced from:
[        ]       _run_mainloop in native_binding.o
[        ]   "_g_type_check_instance_cast", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]   "_gst_bin_add_many", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]   "_gst_bin_get_type", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]   "_gst_element_factory_make", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]       _setup_pipeline in native_binding.o
[        ]       _setup_pipeline in native_binding.o
[        ]   "_gst_element_link_many", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]   "_gst_element_set_state", referenced from:
[        ]       _start_pipeline in native_binding.o
[        ]       _free_resource in native_binding.o
[        ]   "_gst_init", referenced from:
[        ]       _init in native_binding.o
[        ]   "_gst_object_unref", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ]       _setup_pipeline in native_binding.o
[        ]       _start_pipeline in native_binding.o
[        ]       _free_resource in native_binding.o
[        ]   "_gst_pipeline_new", referenced from:
[        ]       _setup_pipeline in native_binding.o
[        ] ld: symbol(s) not found for architecture x86_64
...

Notice the last line: the error is from ld, which is the linker stage of the build. We need to instruct the linker to link against GStreamer. Add the following linking options to native_binding/macos/native_binding.podspec:

...
  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES',
   'HEADER_SEARCH_PATHS' => '"/Library/Frameworks/GStreamer.framework/Headers"',
   'LD_RUNPATH_SEARCH_PATHS' => ['"/Library/Frameworks"','"/Library/Frameworks/GStreamer.framework/Libraries"'],
   'OTHER_LDFLAGS' => '" -L/Library/Frameworks/GStreamer.framework/Libraries -F/Library/Frameworks -framework GStreamer "'
  }
...

Now, if you run the build command again, the build should succeed:

...
[  +14 ms] ** BUILD SUCCEEDED **
[  +44 ms] Building macOS application... (completed in 55.1s)
[   +2 ms] "flutter macos" took 64,392ms.
[  +22 ms] ensureAnalyticsSent: 17ms
[        ] Running 0 shutdown hooks
[        ] Shutdown hooks complete
[        ] exiting with code 0

After running the app, you should hear a sine wave.

Debugging

Like on linux and windows, you can debug native code by adding the following to the configurations section of .vscode/launch.json:

        {
            "name": "MacOS Native",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceRoot}/build/macos/Build/Products/Debug/fltgst.app",
            "MIMode": "lldb",
            "cwd": "${fileDirname}"
        }

GitHub Repository

You can find the repository and the updated files for this tutorial at:

Reference

pod_target_xcconfig reference: https://developer.apple.com/documentation/xcode/build-settings-reference