QtMultimedia on Android: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
(22 intermediate revisions by 4 users not shown)
Line 5: Line 5:


== Building QtMultimedia with FFmpeg ==
== Building QtMultimedia with FFmpeg ==
Before we start building FFmpeg there are some prerequisites that should be taken into account.
'''For windows'''
# Install Msys2 from [[/www.msys2.org/|msys2.org]]
# Complete the steps and open Msys2
# Update package databases ''pacman -Syu''
# Update rest of base packages ''pacman -Su''
# Install ''Mingw-w64:''  ''pacman -S --needed base-devel mingw-w64-x86_64-toolchain''
# Install ''CMake''  : pacman -S mingw-w64-x86_64-cmake
# Install ''Ninja'' : pacman -S mingw-w64-x86_64-ninja
# Make sure to launch '''MSYS2 MinGW 64-bit'''
Then follow the instructions below make sure you run the script using MSYS2 MinGW 64-bit


=== 1- Clone the FFmpeg Repository ===
=== 1- Clone the FFmpeg Repository ===
Start by cloning the official FFmpeg repository:<syntaxhighlight>
Start by cloning the official FFmpeg repository:<syntaxhighlight lang="sh">
git clone git@source.ffmpeg.org:ffmpeg
git clone https://github.com/FFmpeg/FFmpeg.git
</syntaxhighlight>
</syntaxhighlight>


=== 2- Create a Build Script ===
=== 2- Create a Build Script ===
Copy the following script into a file named '''build-ffmpeg-android.sh'''. This script will be used to build FFmpeg for Android:<syntaxhighlight lang="sh">
Copy the following script into a file named '''build-ffmpeg-android.sh'''. This script will be used to build FFmpeg for Android:<syntaxhighlight lang="sh" line="1">
#!/bin/bash
#!/bin/bash


helpFunction() {
helpFunction() {
     echo "Usage: ./build-ffmpeg-android.sh --arch=ARCH --install-path=PATH"
     echo "Usage: ./build-ffmpeg-android.sh --target-arch=ARCH --host-arch=ARCH --install-path=PATH"
     echo -e "\t--arch           Select architecture [aarch64, armv7, x86, x86_64]"
     echo -e "\t--target-arch     Select target architecture [aarch64, armv7, x86, x86_64]"
    echo -e "\t--host-arch    Select the host machine architecture [linux-x86_64, darwin-x86_64, windows-x86_64]"
     echo -e "\t--install-path    Install in PATH used in make install, full path please"
     echo -e "\t--install-path    Install in PATH used in make install, full path please"
     exit 1
     exit 1
Line 25: Line 40:
for opt in "$@"; do
for opt in "$@"; do
     case "$opt" in
     case "$opt" in
         --arch=*)
         --target-arch=*)
             ARCH="${opt#*=}"
             ARCH="${opt#*=}"
         ;;
         ;;
Line 31: Line 46:
             INSTALL_PATH="${opt#*=}"
             INSTALL_PATH="${opt#*=}"
         ;;
         ;;
--host-arch=*)
            HOST_ARCH="${opt#*=}"
        ;;
         *)
         *)
             helpFunction
             helpFunction
Line 38: Line 57:


# Check for empty parameters
# Check for empty parameters
if [ -z "$ARCH" ] || [ -z "$INSTALL_PATH" ]; then
if [ -z "$ARCH" ] || [ -z "$HOST_ARCH" ] || [ -z "$INSTALL_PATH" ]; then
     echo "Some or all of the parameters are empty"
     echo "Some or all of the parameters are empty"
     helpFunction
     helpFunction
Line 44: Line 63:


# Check for required environment variables
# Check for required environment variables
if [ -z "$ANDROID_SDK_ROOT" ] || [ -z "$ANDROID_NDK_ROOT" ] || [ -z "$HOST_ARCH" ] || [ -z "$FFMPEG_LIBRARY_PATH" ]; then
if [ -z "$ANDROID_NDK_ROOT" ] || [ -z "$FFMPEG_LIBRARY_PATH" ]; then
     echo "Please set ANDROID_SDK_ROOT, ANDROID_NDK_ROOT, HOST_ARCH, and FFMPEG_LIBRARY_PATH."
     echo "Please set ANDROID_NDK_ROOT, HOST_ARCH, and FFMPEG_LIBRARY_PATH."
     exit 1
     exit 1
fi
fi
Line 86: Line 105:
--cc=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang
--cc=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang
--cxx=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang++
--cxx=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang++
--strip=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/llvm-strip
--disable-autodetect
--disable-autodetect
--enable-neon
--enable-neon
Line 91: Line 111:
"
"


export LDFLAGS="-L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/sysroot/usr/lib/${TOOLCHAIN_ARCH} -L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/sysroot/usr/lib/${TOOLCHAIN_ARCH}/24 -lm -ldl -llog"
export CFLAGS="-O3 -Wl,exclude-libs,libgcc.a,libunwind.a"
export CFLAGS="-O3 -Wl,exclude-libs,libgcc.a,libunwind.a"


COMMON_OPTIONS="
COMMON_OPTIONS="
--prefix=${INSTALL_PATH}
--prefix=${INSTALL_PATH}
--enable-static
--enable-shared
--disable-shared
--disable-static
--host-os=${HOST_ARCH}
--host-os=${HOST_ARCH}
--install-name-dir=${INSTALL_PATH}
--install-name-dir=${INSTALL_PATH}
Line 118: Line 137:
make -j8 install
make -j8 install
popd
popd
 
</syntaxhighlight>'''Note:''' When building FFmpeg with openssl dependencies. Make sure the below environment variables are set<syntaxhighlight lang="sh">
export ANDROID_OPENSSL_INCLUDE=openssl_include_location
export ANDROID_OPENSSL_LIBS=openssl_libs_location
</syntaxhighlight>Please add the flags below during FFmpeg configuration ''(Line 104'')<syntaxhighlight lang="shell">
--enable-openssl --extra-cflags=-I${ANDROID_OPENSSL_INCLUDE} --extra-ldflags=-L${ANDROID_OPENSSL_LIBS}
</syntaxhighlight>
</syntaxhighlight>


=== 3- Set Environment Variables ===
=== 3- Set Environment Variables ===
Set the environment variables as they are needed to build ffmpeg<syntaxhighlight lang="shell">
Set the environment variables as they are needed to build ffmpeg<syntaxhighlight lang="shell">
export ANDROID_SDK_ROOT=android_sdk_location (i.e ~/Library/Android/sdk)
export ANDROID_NDK_ROOT=android_ndk_location (i.e ~/Library/Android/sdk/ndk/25.1.8937393) (in windows paths are like =/c/Users/usr/AppData/Local/Android/Sdk/ndk/25.1.8937393)
export ANDROID_NDK_ROOT=android_ndk_location (i.e ~/Library/Android/sdk/ndk/25.1.8937393)
export HOST_ARCH="darwin-x86_64"  // or "linux-x86_64"
export FFMPEG_LIBRARY_PATH=cloned_ffmpeg_location (i.e ~/Workspace/Ffmpeg/ffmpeg-android/ffmpeg)
export FFMPEG_LIBRARY_PATH=cloned_ffmpeg_location (i.e ~/Workspace/Ffmpeg/ffmpeg-android/ffmpeg)
</syntaxhighlight>
</syntaxhighlight>
Note: The <code>FFMPEG_LIBRARY_PATH</code> variable is not needed for configuring Qt.


=== 4- Build FFmpeg for Android ===
=== 4- Build FFmpeg for Android ===
Run the build script to build FFmpeg for the specified architecture:<syntaxhighlight lang="shell">
Run the build script to build FFmpeg for the specified architecture:<syntaxhighlight lang="shell">
sh build-ffmpeg-android.sh --arch=aarch64 --install-path=desired_install_path (i.e ../build/arm64-v8a)
sh build-ffmpeg-android.sh --target-arch=aarch64 --host-arch=darwin-x86_64 (for windows: windows-x86_64)--install-path=desired_install_path  
</syntaxhighlight>
</syntaxhighlight>


=== 5- Configure and Build QtMultimedia ===
=== 5- Configure and Build QtMultimedia ===
<syntaxhighlight lang="sh">
 
export ANDROID_OPENSSL_INCLUDE=openssl_include_location
After generating the FFmpeg libraries, configure QtMultimedia with the appropriate flags:
export ANDROID_OPENSSL_LIBS=openssl_libs_location
 
<syntaxhighlight lang="shell">
cd /path/to/qt/build-tree
/path/to/qt/source/configure .... -- -D FFMPEG_DIR:PATH=ffmpeg_install_path -D QT_DEPLOY_FFMPEG=ON
</syntaxhighlight>
</syntaxhighlight>
After generating the FFmpeg libraries, configure QtMultimedia with the appropriate flags:<syntaxhighlight lang="shell">
 
cd /path/to/qt/source
where <pre>ffmpeg_install_path</pre> is the same path as passed into the <pre>build-ffmpeg-android.sh</pre> script as the <pre>--install-path</pre>.
./configure ....
 
If openssl is enabled during FFmpeg configuration make sure you add to the above command <syntaxhighlight lang="shell">
-D OPENSSL_INCLUDE_DIR=openssl_include_folder_path  
-D OPENSSL_INCLUDE_DIR=openssl_include_folder_path  
-D FFMPEG_DIR:PATH=ffmpeg_built_libs_path
</syntaxhighlight>
</syntaxhighlight>Check how to build [https://doc-snapshots.qt.io/qt6-dev/android-building.html#building Qt from source for Android]
 
For more information on how to build qt for Android check [https://doc-snapshots.qt.io/qt6-dev/android-building.html#building Qt from source for Android]

Latest revision as of 14:01, 23 September 2024

Overview

With the introduction of FFmpeg in QtMultimedia for Android starting from version 6.7, developers now have a robust option for handling multimedia tasks. This shift is significant as the MediaCodec-based backend is deprecated from Qt 6.8 and is scheduled for removal in Qt 7.0. Therefore, it is highly recommended to transition to FFmpeg for future-proofing your multimedia applications on Android.

This guide will walk you through the steps to build QtMultimedia with FFmpeg on Android.

Building QtMultimedia with FFmpeg

Before we start building FFmpeg there are some prerequisites that should be taken into account.

For windows

  1. Install Msys2 from msys2.org
  2. Complete the steps and open Msys2
  3. Update package databases pacman -Syu
  4. Update rest of base packages pacman -Su
  5. Install Mingw-w64: pacman -S --needed base-devel mingw-w64-x86_64-toolchain
  6. Install CMake  : pacman -S mingw-w64-x86_64-cmake
  7. Install Ninja : pacman -S mingw-w64-x86_64-ninja
  8. Make sure to launch MSYS2 MinGW 64-bit

Then follow the instructions below make sure you run the script using MSYS2 MinGW 64-bit

1- Clone the FFmpeg Repository

Start by cloning the official FFmpeg repository:

git clone https://github.com/FFmpeg/FFmpeg.git

2- Create a Build Script

Copy the following script into a file named build-ffmpeg-android.sh. This script will be used to build FFmpeg for Android:

#!/bin/bash

helpFunction() {
    echo "Usage: ./build-ffmpeg-android.sh --target-arch=ARCH --host-arch=ARCH --install-path=PATH"
    echo -e "\t--target-arch     Select target architecture [aarch64, armv7, x86, x86_64]"
    echo -e "\t--host-arch    Select the host machine architecture [linux-x86_64, darwin-x86_64, windows-x86_64]"
    echo -e "\t--install-path    Install in PATH used in make install, full path please"
    exit 1
}

# Parse command-line options
for opt in "$@"; do
    case "$opt" in
        --target-arch=*)
            ARCH="${opt#*=}"
        ;;
        --install-path=*)
            INSTALL_PATH="${opt#*=}"
        ;;
	--host-arch=*)
            HOST_ARCH="${opt#*=}"
        ;;

        *)
            helpFunction
        ;;
    esac
done

# Check for empty parameters
if [ -z "$ARCH" ] || [ -z "$HOST_ARCH" ] || [ -z "$INSTALL_PATH" ]; then
    echo "Some or all of the parameters are empty"
    helpFunction
fi

# Check for required environment variables
if [ -z "$ANDROID_NDK_ROOT" ] || [ -z "$FFMPEG_LIBRARY_PATH" ]; then
    echo "Please set ANDROID_NDK_ROOT, HOST_ARCH, and FFMPEG_LIBRARY_PATH."
    exit 1
fi

# Setup architecture-specific variables
case "$ARCH" in
    aarch64)
        TOOLCHAIN_ARCH="aarch64-linux-android"
        CPU="armv8-a"
    ;;
    armv7)
        TOOLCHAIN_ARCH="armv7a-linux-androideabi"
        CPU="armv7-a"
    ;;
    x86)
        TOOLCHAIN_ARCH="i686-linux-android"
        CPU="i686"
    ;;
    x86_64)
        TOOLCHAIN_ARCH="x86_64-linux-android"
        CPU="x86-64"
    ;;
    *)
        echo "Invalid architecture: $ARCH"
        helpFunction
    ;;
esac

ANDROID_OPTIONS="
--target-os=android
--arch=${ARCH}
--cpu=${CPU}
--enable-cross-compile
--enable-jni
--enable-mediacodec
--enable-pthreads
--disable-indev=android_camera
--sysroot=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/sysroot
--sysinclude=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/sysroot/usr/include/
--cc=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang
--cxx=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/${TOOLCHAIN_ARCH}24-clang++
--strip=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_ARCH}/bin/llvm-strip
--disable-autodetect
--enable-neon
--disable-asm
"

export CFLAGS="-O3 -Wl,exclude-libs,libgcc.a,libunwind.a"

COMMON_OPTIONS="
--prefix=${INSTALL_PATH}
--enable-shared
--disable-static
--host-os=${HOST_ARCH}
--install-name-dir=${INSTALL_PATH}
--disable-logging
--disable-debug
--disable-programs
--enable-pic
"

pushd ${FFMPEG_LIBRARY_PATH}
make clean
make distclean

echo "./configure ${COMMON_OPTIONS} ${ANDROID_OPTIONS}"
./configure ${COMMON_OPTIONS} ${ANDROID_OPTIONS}

sed -i "s/-fPIE/-fPIC/" ffbuild/config.mak
sed -i "s/-pie/-pic/" ffbuild/config.mak

make -j8 install
popd

Note: When building FFmpeg with openssl dependencies. Make sure the below environment variables are set

export ANDROID_OPENSSL_INCLUDE=openssl_include_location 
export ANDROID_OPENSSL_LIBS=openssl_libs_location

Please add the flags below during FFmpeg configuration (Line 104)

--enable-openssl --extra-cflags=-I${ANDROID_OPENSSL_INCLUDE} --extra-ldflags=-L${ANDROID_OPENSSL_LIBS}

3- Set Environment Variables

Set the environment variables as they are needed to build ffmpeg

export ANDROID_NDK_ROOT=android_ndk_location (i.e ~/Library/Android/sdk/ndk/25.1.8937393) (in windows paths are like =/c/Users/usr/AppData/Local/Android/Sdk/ndk/25.1.8937393)
export FFMPEG_LIBRARY_PATH=cloned_ffmpeg_location (i.e ~/Workspace/Ffmpeg/ffmpeg-android/ffmpeg)

Note: The

FFMPEG_LIBRARY_PATH

variable is not needed for configuring Qt.

4- Build FFmpeg for Android

Run the build script to build FFmpeg for the specified architecture:

sh build-ffmpeg-android.sh --target-arch=aarch64 --host-arch=darwin-x86_64 (for windows: windows-x86_64)--install-path=desired_install_path

5- Configure and Build QtMultimedia

After generating the FFmpeg libraries, configure QtMultimedia with the appropriate flags:

cd /path/to/qt/build-tree
/path/to/qt/source/configure .... -- -D FFMPEG_DIR:PATH=ffmpeg_install_path -D QT_DEPLOY_FFMPEG=ON

where

ffmpeg_install_path

is the same path as passed into the

build-ffmpeg-android.sh

script as the

--install-path

. If openssl is enabled during FFmpeg configuration make sure you add to the above command

-D OPENSSL_INCLUDE_DIR=openssl_include_folder_path

For more information on how to build qt for Android check Qt from source for Android