Building Qt Multimedia with FFmpeg: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
(4 intermediate revisions by the same user not shown)
Line 20: Line 20:
#Install msys2 from provisioning: Run qt6\coin\provisioning\common\windows\install-msys2.ps1 as admin
#Install msys2 from provisioning: Run qt6\coin\provisioning\common\windows\install-msys2.ps1 as admin
#*Needed by provisioning script for FFmpeg because FFmpeg requires tools from msys to configure
#*Needed by provisioning script for FFmpeg because FFmpeg requires tools from msys to configure
#Install FFmpeg from provisioning: Run qt6\coin\provisioning\common\windows\install-ffmpeg.ps1 as admin
#If you want to enable '''debugging''' of FFmpeg, edit  qt6\coin\provisioning\common\shared\ffmpeg_config_options.txt
#*Replace <code enclose="none">--disable-debug</code> with <code enclose="none">--enable-debug --disable-optimizations</code>
#*<code enclose="none">--disable-optimizations&lt</code> will use MSVC <code enclose="none">/O1</code>, which still inlines functions and makes debugging hard.
#*Adding <code enclose="none">--extra-cflags=-Ob0</code> reduces optimizations further, making debugging easier. Note that FFmpeg does not support compiling without any optimizations set <code enclose="none">-Od</code>. Doing so will cause linker errors.
#Install FFmpeg from provisioning: Run qt6\coin\provisioning\common\windows\install-ffmpeg.ps1 as admin  
#*Since I only need MSVC build, I edit the install-ffmpeg.ps1 first, to comment out unnecessary versions
#*Since I only need MSVC build, I edit the install-ffmpeg.ps1 first, to comment out unnecessary versions
#*This sets FFMPEG_DIR=C:\FFmpeg-n6.0\build\msvc\installed\
#*This builds FFmpeg and sets FFMPEG_DIR=C:\FFmpeg-n6.0\build\msvc\installed\


==== Option 2: Building FFmpeg on Windows using vcpkg ====
====Option 2: Building FFmpeg on Windows using vcpkg====
If you don't already have vcpkg, install vcpkg:<blockquote>git clone <nowiki>https://github.com/microsoft/vcpkg</nowiki></blockquote>From within the new vcpkg directory, run<blockquote>bootstrap-vcpkg.bat</blockquote>Now, building FFmpeg is done by executing<blockquote>vcpkg install ffmpeg[core,swresample,swscale,avdevice]:x64-windows</blockquote>This will download all necessary dependencies and build FFmpeg into C:\dev\vcpkg\installed\x64-windows if vcpkg was cloned into C:\dev
If you don't already have vcpkg, install vcpkg:<blockquote>git clone <nowiki>https://github.com/microsoft/vcpkg</nowiki></blockquote>From within the new vcpkg directory, run<blockquote>bootstrap-vcpkg.bat</blockquote>Now, building FFmpeg is done by executing<blockquote>vcpkg install ffmpeg[core,swresample,swscale,avdevice]:x64-windows</blockquote>This will download all necessary dependencies and build FFmpeg into C:\dev\vcpkg\installed\x64-windows if vcpkg was cloned into C:\dev
'''Option 3: Building manually with MSYS2 (on Windows)'''
#Install MSYS2
#Start VS ''x64 Native Tools Command Prompt''
#Set environment variable MSYS2_PATH_TYPE to make MSYS2 inherit environment variable <code>set MSYS2_PATH_TYPE=inherit</code>
#First time, download necessary MSYS2 packages <code>pacman-key --init;pacman-key --populate msys2;pacman-key --refresh;pacman -S --noconfirm perl make yasm diffutils</code>
#Configure: <code>FFmpeg_install_dir/configure --prefix=installed --toolchain=msvc --disable-doc --enable-debug --enable-network --disable-lzma --enable-pic --disable-vulkan --disable-v4l2-m2m --disable-decoder=truemotion1 --enable-shared --disable-static --disable-optimizations --extra-cflags=-Ob0</code>
# Install: <code>make install -j</code>


===Configure Qt main build===
===Configure Qt main build===
Line 42: Line 55:
     "configurePresets": [
     "configurePresets": [
         {
         {
             "name": "msvc-64",
             "name": "msvc",
             "hidden": true,
             "hidden": true,
             "condition": {
             "condition": {
Line 64: Line 77:
         },
         },
         {
         {
             "name": "Debug",
             "name": "qtmultimedia",
             "hidden": true,
             "inherits": "msvc",
            "cacheVariables": {
             "binaryDir": "D:/qt/build/qtmultimedia",
                "CMAKE_BUILD_TYPE": "Debug"
            }
        },
        {
             "name": "qt6-dev-base",
            "hidden": true,
             "cacheVariables": {
             "cacheVariables": {
                 "FEATURE_developer_build": true,
                 "FEATURE_developer_build": true,
                "BUILD_qttools": false,
                 "QT_BUILD_EXAMPLES": true,
                "BUILD_qtdoc": false,
                "BUILD_qttranslations": false,
                 "QT_BUILD_EXAMPLES": false,
                 "QT_BUILD_EXAMPLES_BY_DEFAULT": false,
                 "QT_BUILD_EXAMPLES_BY_DEFAULT": false,
                 "QT_BUILD_EXAMPLES_AS_EXTERNAL": false,
                 "QT_BUILD_EXAMPLES_AS_EXTERNAL": false,
                 "QT_BUILD_TESTS": false,
                 "QT_BUILD_TESTS": true,
                 "QT_BUILD_TESTS_BY_DEFAULT": false
                 "QT_BUILD_TESTS_BY_DEFAULT": false,
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_PREFIX_PATH": "D:/qt/build/dev/qtbase/",
                "QT_DEPLOY_FFMPEG": true,
                "FFMPEG_DIR": "C:/ffmpeg-n6.1.1/build/msvc/installed"
             },
             },
             "environment": {
             "environment": {
                 "PATH": "D:/qt/build/dev/qtbase/bin;$penv{PATH}"
                 "PATH": "D:/qt/build/dev/qtbase/bin;$penv{PATH}"
            }
        },
        {
            "name": "qt6-dev-debug",
            "hidden": true,
            "inherits": [
                "qt6-dev-base",
                "msvc-64",
                "Debug"
            ],
            "cacheVariables": {
                "CMAKE_PREFIX_PATH": "D:/qt/build/dev/qtbase/"
            },
            "environment": {
                "PATH": "D:/qt/build/dev/qtbase/bin;$penv{PATH}"
            }
        },
        {
            "name": "QtMultimedia",
            "inherits": "qt6-dev-debug",
            "binaryDir": "D:/qt/build/qtmultimedia/",
            "cacheVariables": {
                "QT_BUILD_EXAMPLES": true,
                "QT_BUILD_EXAMPLES_BY_DEFAULT": true,
                "QT_BUILD_TESTS": true,
                "QT_BUILD_TESTS_BY_DEFAULT": true,
                "QT_BUILD_EXAMPLES_AS_EXTERNAL": false,
                "QT_BUILD_MANUAL_TESTS": false,
                "QT_DEPLOY_FFMPEG": true,
                "FEATURE_ffmpeg": true,
                "FFMPEG_DIR": "C:\\ffmpeg-n6.0\\build\\msvc\\installed"
             }
             }
         }
         }
Line 122: Line 99:
     "buildPresets": [
     "buildPresets": [
         {
         {
             "name": "Build-Qt-Multimedia-MSVC-Debug-64",
             "name": "Build Qt Multimedia",
            "displayName": "Build Qt Multimedia MSVC Debug 64",
             "configurePreset": "qtmultimedia"
             "configurePreset": "QtMultimedia"
         }
         }
     ]
     ]
}
}
</code>
</code>

Revision as of 13:24, 11 April 2024

This page shows one example of how to build Qt Multimedia with the FFmpeg backend on Windows. Note that there are many ways to achieve the same result with Qt, but this is how I do it.

Build setup assumed in this description

The commands in this description assumes that the build setup is like in the below list. If your setup is different, adjust the commands accordingly.

  • OS: Windows 11 with dev drive mounted on D: (Using a dev drive makes builds faster when using Windows Defender antivirus)
  • Qt source tree: D:\qt\qt6\
  • Build directory containing all builds: D:\qt\build\
  • Main (host) build for dev branch: D:\qt\build\dev\
  • Visual Studio 2022 (MSVC)
  • Have cmake in path

Developer setup for Qt Multimedia on Windows

Building FFmpeg

Option 1: Building FFmpeg on Windows using Qt's provisioning scripts

For building FFmpeg, Qt's own provisioning scripts can be very useful. These scripts are used in our CI infrastructure when building FFmpeg, but can also be used by developers

  1. Install 7-zip from provisioning: Run qt6\coin\provisioning\common\windows\install-sevenzip.ps1 as admin
    • Needed by provisioning script for FFmpeg to unzip downloaded FFmpeg
  2. Install msys2 from provisioning: Run qt6\coin\provisioning\common\windows\install-msys2.ps1 as admin
    • Needed by provisioning script for FFmpeg because FFmpeg requires tools from msys to configure
  3. If you want to enable debugging of FFmpeg, edit qt6\coin\provisioning\common\shared\ffmpeg_config_options.txt
    • Replace --disable-debug with --enable-debug --disable-optimizations
    • --disable-optimizations&lt will use MSVC /O1, which still inlines functions and makes debugging hard.
    • Adding --extra-cflags=-Ob0 reduces optimizations further, making debugging easier. Note that FFmpeg does not support compiling without any optimizations set -Od. Doing so will cause linker errors.
  4. Install FFmpeg from provisioning: Run qt6\coin\provisioning\common\windows\install-ffmpeg.ps1 as admin
    • Since I only need MSVC build, I edit the install-ffmpeg.ps1 first, to comment out unnecessary versions
    • This builds FFmpeg and sets FFMPEG_DIR=C:\FFmpeg-n6.0\build\msvc\installed\

Option 2: Building FFmpeg on Windows using vcpkg

If you don't already have vcpkg, install vcpkg:

git clone https://github.com/microsoft/vcpkg

From within the new vcpkg directory, run

bootstrap-vcpkg.bat

Now, building FFmpeg is done by executing

vcpkg install ffmpeg[core,swresample,swscale,avdevice]:x64-windows

This will download all necessary dependencies and build FFmpeg into C:\dev\vcpkg\installed\x64-windows if vcpkg was cloned into C:\dev

Option 3: Building manually with MSYS2 (on Windows)

  1. Install MSYS2
  2. Start VS x64 Native Tools Command Prompt
  3. Set environment variable MSYS2_PATH_TYPE to make MSYS2 inherit environment variable
    set MSYS2_PATH_TYPE=inherit
    
  4. First time, download necessary MSYS2 packages
    pacman-key --init;pacman-key --populate msys2;pacman-key --refresh;pacman -S --noconfirm perl make yasm diffutils
    
  5. Configure:
    FFmpeg_install_dir/configure --prefix=installed --toolchain=msvc --disable-doc --enable-debug --enable-network --disable-lzma --enable-pic --disable-vulkan --disable-v4l2-m2m --disable-decoder=truemotion1 --enable-shared --disable-static --disable-optimizations --extra-cflags=-Ob0
    
  6. Install:
    make install -j
    

Configure Qt main build

I build Qt as stand-alone module to make builds run faster when working in QtMultimedia. But first, we need to build the necessary dependencies. I do this from command line with D:\qt\build\dev as current directory. Note that if you did build FFmpeg with vcpkg, you need to update the -DFFMPEG_DIR argument to point to the C:\dev\vcpkg\installed\x64-windows directory (not the bin-directory inside).

..\..\qt6\configure.bat -debug -developer-build -init-submodules -submodules qtmultimedia -nomake tests -nomake examples -codereview-username johanseg -- -DFFMPEG_DIR=C:\FFmpeg-n6.0\build\msvc\installed --fresh & ninja

I work almost exclusively using debug builds. If you need a release build, configure the release build in a separate build directory. This is a developer build, and we can use D:\qt\build\dev\qtbase\ as CMAKE_PREFIX_PATH when developing other Qt modules. By configuring this way, QtMultimedia is built, which is not strictly necessary since I develop QtMultimedia in a separate build tree, but it is an easy way to make sure all QtMultimedia dependencies are built.

Configure Qt multimedia

I configure QtMultimedia using a CMakeUserPresets.json file that is located in D:\qt\qt6\qtmultimedia instead of using a configure script. This way, I can open the D:\qt\qt6\qtmultimedia as a folder in Visual Studio and configure it from there.

The benefit of using CMakeUserPresets.json is that Visual Studio knows how to debug the tests and examples. I have not found a way that allows Visual Studio to use an existing CMakeCache as a starting point.

To make sure FFmpeg is deployed from the provisioning or vcpkg build into the Qt bin directory, make sure to specify the QT_DEPLOY_FFMPEG=ON CMake variable.

{
    "version": 5,
    "configurePresets": [
        {
            "name": "msvc",
            "hidden": true,
            "condition": {
                "type": "equals",
                "lhs": "${hostSystemName}",
                "rhs": "Windows"
            },
            "generator": "Ninja",
            "cacheVariables": {
                "CMAKE_CXX_COMPILER": "cl.exe",
                "CMAKE_C_COMPILER": "cl.exe"
            },
            "toolset": {
                "value": "v143,host=x64",
                "strategy": "external"
            },
            "architecture": {
                "value": "x64",
                "strategy": "external"
            }
        },
        {
            "name": "qtmultimedia",
            "inherits": "msvc",
            "binaryDir": "D:/qt/build/qtmultimedia",
            "cacheVariables": {
                "FEATURE_developer_build": true,
                "QT_BUILD_EXAMPLES": true,
                "QT_BUILD_EXAMPLES_BY_DEFAULT": false,
                "QT_BUILD_EXAMPLES_AS_EXTERNAL": false,
                "QT_BUILD_TESTS": true,
                "QT_BUILD_TESTS_BY_DEFAULT": false,
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_PREFIX_PATH": "D:/qt/build/dev/qtbase/",
                "QT_DEPLOY_FFMPEG": true,
                "FFMPEG_DIR": "C:/ffmpeg-n6.1.1/build/msvc/installed"
            },
            "environment": {
                "PATH": "D:/qt/build/dev/qtbase/bin;$penv{PATH}"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "Build Qt Multimedia",
            "configurePreset": "qtmultimedia"
        }
    ]
}