Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtmultimedia-building-FFmpeg-ios.qdoc
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\page qtmultimedia-building-ffmpeg-ios.html
6\title Building FFmpeg from source for iOS on macOS
7\brief This document describes how to build FFmpeg from source code.
8
9This page explains how to configure and build \l{FFmpeg} for iOS as frameworks.
10Compilation for iOS is a cross-compilation and presumes using macOS as a host system.
11The required steps are:
12
13\list
14\li Preparing build environment
15\li Getting the FFmpeg source code
16\li Configuring FFmpeg from the command line
17\li Building dynamic libraries
18\li Creating iOS frameworks from FFmpeg libraries
19\li Creating XCFrameworks
20\li Embedding frameworks
21\endlist
22
23\note The following documentation assumes that you work with FFmpeg libraries and code
24under \c{~/ffmpeg}.
25
26\section1 Preparing build environment
27
28The build environment for iOS is provided by Apple's Xcode application, which includes
29the toolchain (compiler, linker, and other tools), and the iOS platform-SDK (headers
30and libraries) that you build and link against.
31
32\section1 Getting the FFmpeg source code
33
34You can get the FFmpeg source code in these ways:
35
36\list
37\li Download from the
38\l{https://ffmpeg.org/download.html#get-sources}{FFmpeg download page}.
39\li Clone from git. For example, these commands clone the version 7.1.2 of the
40FFmpeg sources to \c{~/ffmpeg/ffmpeg_src}.
41\badcode
42cd ~/ffmpeg/
43git clone --branch n7.1.2 https://git.ffmpeg.org/ffmpeg.git ffmpeg_src
44\endcode
45\endlist
46
47\note It is recommended to use the same FFmpeg version as documented in the
48\l{Qt Multimedia}{Qt Multimedia main page}.
49
50\section1 Configuring and building FFmpeg
51
52Create a \c build and \c installed directories inside the \c{~/ffmpeg} directory and
53navigate into \c build:
54
55\badcode
56mkdir ~/ffmpeg/build
57mkdir ~/ffmpeg/installed
58cd ~/ffmpeg/build
59\endcode
60
61To configure FFmpeg, run:
62
63\badcode
64../ffmpeg_src/configure --disable-programs --disable-doc --enable-network --enable-shared --disable-static \
65 --sysroot="$(xcrun --sdk iphoneos --show-sdk-path)" \
66 --enable-cross-compile \
67 --arch=arm64 \
68 --prefix=../installed \
69 --cc="xcrun --sdk iphoneos clang -arch arm64" \
70 --cxx="xcrun --sdk iphoneos clang++ -arch arm64" \
71 --extra-ldflags="-miphoneos-version-min=16.0" \
72 --install-name-dir='@rpath' \
73 --disable-audiotoolbox
74\endcode
75
76The command line programs and documentation are not needed; network features
77should be enabled. We build shared libraries and don't need static libraries (omit
78\c{--disable-static} to build static libraries). \c{--sysroot} specifies the root of cross-build
79tree. The \c{--prefix} argument specifies a path where the FFmpeg libraries are installed
80after building. We build on macOS host for iOS target so we enable cross compilation.
81\c{--extra-ldflags} set the minimum version of iOS.
82\c{--install-name-dir} is a string specifying the directory portion of the "install_name"
83field of shared libraries on Apple platforms for installed targets.
84AudioToolBox is disabled, since FFmpeg is using parts of AudioToolBox
85framework which are not available on iOS.
86
87\note In the example above, replacing 'iphoneos' with 'iphonesimulator',
88and 'miphoneos-version' with 'mios-simulator-version-min', configures
89FFmpeg to be built as libraries suitable for iOS simulator.
90
91To get help on other configuration options, run:
92\badcode
93../ffmpeg_src/configure --help
94\endcode
95
96After configuration is complete, build FFmpeg libraries:
97
98\badcode
99make -j install
100\endcode
101
102\section1 Creating iOS frameworks from FFmpeg libraries
103
104To work in iOS applications, FFmpeg dynamic libraries have to
105be converted into frameworks and embedded into application bundles.
106A framework is a hierarchical directory that encapsulates resources
107such as a dynamic library, image files, localized strings, header files,
108and reference documentation in a single package. In our case, FFmpeg frameworks
109only contain dynamic libraries and corresponding Info.plist files.
110For example, libavcodec converted to framework becomes \c libavcodec.framework
111directory with these contents:
112
113\list
114\li Info.plist (containing the description of the framework)
115\li libavcodec (dynamic library)
116\endlist
117
118Unlike dynamic libraries we built in the previous step, dynamic libraries
119inside iOS frameworks are unversioned and have no 'dylib' extensions. This requires
120fixing library identification names and dependencies in our dynamic libraries.
121The \c otool utility helps us to find such names. For example:
122
123\badcode
124otool -L ../installed/lib/libavcodec.dylib
125\endcode
126
127gives us these names (we only show FFmpeg-related names):
128
129\badcode
130@rpath/libavcodec.61.dylib (compatibility version 61.0.0, current version 61.19.100)
131@rpath/libswresample.5.dylib (compatibility version 5.0.0, current version 5.3.100)
132@rpath/libavutil.59.dylib (compatibility version 59.0.0, current version 59.39.100)
133\endcode
134
135 To fix these names, use the \c install_name_tool utility. The utility options are:
136
137 \list
138 \li \c {-id} - allows changing the shared library identification name.
139 \li \c {-change} - allows changing the dependent shared library install name.
140 \endlist
141
142This script converts the previously built dynamic libraries to frameworks. The code assumes
143that you run it from the \c build directory and the frameworks are located in
144\c{~/ffmpeg/installed/framework}:
145
146\badcode
147#!/usr/bin/env bash
148
149# Creates an Info.plist file for a given framework:
150build_info_plist() {
151 local file_path="$1"
152 local framework_name="$2"
153 local framework_id="$3"
154
155 # Minimum version must be the same we used when building FFmpeg.
156 local minimum_version_key="MinimumOSVersion"
157 local minimum_os_version="16.0"
158
159 local supported_platforms="iPhoneOS"
160
161 info_plist="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
162<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
163<plist version=\"1.0\">
164<dict>
165 <key>CFBundleDevelopmentRegion</key>
166 <string>en</string>
167 <key>CFBundleExecutable</key>
168 <string>${framework_name}</string>
169 <key>CFBundleIdentifier</key>
170 <string>${framework_id}</string>
171 <key>CFBundleInfoDictionaryVersion</key>
172 <string>6.0</string>
173 <key>CFBundleName</key>
174 <string>${framework_name}</string>
175 <key>CFBundlePackageType</key>
176 <string>FMWK</string>
177 <key>CFBundleShortVersionString</key>
178 <string>7.0.2</string>
179 <key>CFBundleVersion</key>
180 <string>7.0.2</string>
181 <key>CFBundleSignature</key>
182 <string>????</string>
183 <key>${minimum_version_key}</key>
184 <string>${minimum_os_version}</string>
185 <key>CFBundleSupportedPlatforms</key>
186 <array>
187 <string>${supported_platforms}</string>
188 </array>
189 <key>NSPrincipalClass</key>
190 <string></string>
191</dict>
192</plist>"
193 echo $info_plist | tee ${file_path} 1>/dev/null
194}
195
196dylib_regex="^@rpath/.*\.dylib$"
197
198# Creates framework from a dylib file:
199create_framework() {
200 local framework_name="$1"
201 local ffmpeg_library_path="../installed"
202 local framework_complete_path="${ffmpeg_library_path}/framework/${framework_name}.framework/${framework_name}"
203
204 # Create framework directory and copy dylib file to this directory:
205 mkdir -p "${ffmpeg_library_path}/framework/${framework_name}.framework"
206 cp "${ffmpeg_library_path}/lib/${framework_name}.dylib" "${ffmpeg_library_path}/framework/${framework_name}.framework/${framework_name}"
207
208 # Change the shared library identification name, removing version number and 'dylib' extension;
209 # \c Frameworks part of the name is needed since this is where frameworks will be installed in
210 # an application bundle:
211 install_name_tool -id @rpath/Frameworks/${framework_name}.framework/${framework_name} "${framework_complete_path}"
212
213 # Add Info.plist file into the framework directory:
214 build_info_plist "${ffmpeg_library_path}/framework/${framework_name}.framework/Info.plist" "${framework_name}" "io.qt.ffmpegkit."${framework_name}
215 otool -L "$framework_complete_path" | awk '/\t/ {print $1}' | egrep "$dylib_regex" | while read -r dependency_path; do
216 found_name=$(tmp=${dependency_path/*\/}; echo ${tmp/\.*})
217 if [ "$found_name" != "$framework_name" ]
218 then
219 # Change the dependent shared library install name to remove version number and 'dylib' extension:
220 install_name_tool -change "$dependency_path" @rpath/Frameworks/${found_name}.framework/${found_name} "${framework_complete_path}"
221 fi
222 done
223}
224
225ffmpeg_libs="libavcodec libavformat libavutil libswresample libswscale"
226
227for name in $ffmpeg_libs; do
228 create_framework $name
229done
230
231\endcode
232
233\section1 Creating a multiplatform binary framework bundle
234
235An XCFramework bundle is a package that includes frameworks and libraries
236necessary to build for multiple platforms, for example, iOS and iOS simulator.
237To create such a framework, use the \c xcodebuild utility. For example, if
238you have frameworks for iOS and simulator located in \c {~/ffmpeg/installed/arm64}
239and \c {~/ffmpeg/installed/arm64-simulator} directories, the utility arguments look
240like follows:
241
242\badcode
243xcodebuild -create-xcframework -framework ../installed/arm64/libavcodec.framework -framework ../installed/arm64-simulator/libavcodec.framework -output ../installed/framework/libavcodec.xcframework
244\endcode
245
246\section1 Embedding frameworks
247
248Embed the FFmpeg frameworks into an application bundle. For information on how to
249embed frameworks using XCode, refer to
250
251\l{https://developer.apple.com/library/archive/technotes/tn2435/_index.html}{Embedding Frameworks In An App}.
252
253*/