diff --git a/CMakeLists.txt b/CMakeLists.txt
index c3a021ef9296..cfc6937a552b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 3.22.1)
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
+list(APPEND CMAKE_MODULE_PATH
+ ${CMAKE_SOURCE_DIR}/cmake
+ ${CMAKE_SOURCE_DIR}/cmake/modules
+ ${CMAKE_SOURCE_DIR}/cmake/find-modules
+)
#######################################################
# Custom Build Configuration
@@ -60,6 +64,7 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+# set(CMAKE_OPTIMIZE_DEPENDENCIES ON)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release")
if(NOT CMAKE_BUILD_TYPE)
@@ -106,6 +111,10 @@ endif()
set(BUILD_SHARED_LIBS OFF)
+if(CMAKE_BUILD_TYPE STREQUAL "Release")
+ add_compile_definitions(QGC_INSTALL_RELEASE)
+endif()
+
#######################################################
# Qt6 Configuration
#######################################################
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 0aaefbcaf0f1..df97d72b8b91 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/android/src/org/freedesktop/gstreamer/GStreamer.java b/android/src/org/freedesktop/gstreamer/GStreamer.java
new file mode 100644
index 000000000000..066b2152b499
--- /dev/null
+++ b/android/src/org/freedesktop/gstreamer/GStreamer.java
@@ -0,0 +1,105 @@
+/**
+ * Copy this file into your Android project and call init(). If your project
+ * contains fonts and/or certificates in assets, uncomment copyFonts() and/or
+ * copyCaCertificates() lines in init().
+ */
+package org.freedesktop.gstreamer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.system.Os;
+
+public class GStreamer {
+ private static native void nativeInit(Context context) throws Exception;
+
+ public static void init(Context context) throws Exception {
+ //copyFonts(context);
+ //copyCaCertificates(context);
+ nativeInit(context);
+ }
+
+ private static void copyFonts(Context context) {
+ AssetManager assetManager = context.getAssets();
+ File filesDir = context.getFilesDir();
+ File fontsFCDir = new File (filesDir, "fontconfig");
+ File fontsDir = new File (fontsFCDir, "fonts");
+ File fontsCfg = new File (fontsFCDir, "fonts.conf");
+
+ fontsDir.mkdirs();
+
+ try {
+ /* Copy the config file */
+ copyFile (assetManager, "fontconfig/fonts.conf", fontsCfg);
+ /* Copy the fonts */
+ for(String filename : assetManager.list("fontconfig/fonts/truetype")) {
+ File font = new File(fontsDir, filename);
+ copyFile (assetManager, "fontconfig/fonts/truetype/" + filename, font);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void copyCaCertificates(Context context) {
+ AssetManager assetManager = context.getAssets();
+ File filesDir = context.getFilesDir();
+ File sslDir = new File (filesDir, "ssl");
+ File certsDir = new File (sslDir, "certs");
+ File certs = new File (certsDir, "ca-certificates.crt");
+
+ certsDir.mkdirs();
+
+ try {
+ /* Copy the certificates file */
+ copyFile (assetManager, "ssl/certs/ca-certificates.crt", certs);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void copyFile(AssetManager assetManager, String assetPath, File outFile) throws IOException {
+ InputStream in = null;
+ OutputStream out = null;
+ IOException exception = null;
+
+ if (outFile.exists())
+ outFile.delete();
+
+ try {
+ in = assetManager.open(assetPath);
+ out = new FileOutputStream(outFile);
+
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1) {
+ out.write(buffer, 0, read);
+ }
+ out.flush();
+ } catch (IOException e) {
+ exception = e;
+ } finally {
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException e) {
+ if (exception == null)
+ exception = e;
+ }
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException e) {
+ if (exception == null)
+ exception = e;
+ }
+ if (exception != null)
+ throw exception;
+ }
+ }
+}
diff --git a/android/src/org/freedesktop/gstreamer/fontconfig/fonts.conf b/android/src/org/freedesktop/gstreamer/fontconfig/fonts.conf
new file mode 100644
index 000000000000..445d8ce5d730
--- /dev/null
+++ b/android/src/org/freedesktop/gstreamer/fontconfig/fonts.conf
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+ fontconfig/fonts
+
+
+
+ fontconfig
+
+
+
+
+ mono
+
+
+ monospace
+
+
+
+
+
+
+ sans serif
+
+
+ sans-serif
+
+
+
+
+
+
+ sans
+
+
+ sans-serif
+
+
+
+
+
+
+ 0x0020
+ 0x00A0
+ 0x00AD
+ 0x034F
+ 0x0600
+ 0x0601
+ 0x0602
+ 0x0603
+ 0x06DD
+ 0x070F
+ 0x115F
+ 0x1160
+ 0x1680
+ 0x17B4
+ 0x17B5
+ 0x180E
+ 0x2000
+ 0x2001
+ 0x2002
+ 0x2003
+ 0x2004
+ 0x2005
+ 0x2006
+ 0x2007
+ 0x2008
+ 0x2009
+ 0x200A
+ 0x200B
+ 0x200C
+ 0x200D
+ 0x200E
+ 0x200F
+ 0x2028
+ 0x2029
+ 0x202A
+ 0x202B
+ 0x202C
+ 0x202D
+ 0x202E
+ 0x202F
+ 0x205F
+ 0x2060
+ 0x2061
+ 0x2062
+ 0x2063
+ 0x206A
+ 0x206B
+ 0x206C
+ 0x206D
+ 0x206E
+ 0x206F
+ 0x2800
+ 0x3000
+ 0x3164
+ 0xFEFF
+ 0xFFA0
+ 0xFFF9
+ 0xFFFA
+ 0xFFFB
+
+
+
+ 30
+
+
+
+
+
diff --git a/android/src/org/freedesktop/gstreamer/fontconfig/fonts/Ubuntu-R.ttf b/android/src/org/freedesktop/gstreamer/fontconfig/fonts/Ubuntu-R.ttf
new file mode 100644
index 000000000000..45a038bade52
Binary files /dev/null and b/android/src/org/freedesktop/gstreamer/fontconfig/fonts/Ubuntu-R.ttf differ
diff --git a/cmake/Qt6QGCConfiguration.cmake b/cmake/Qt6QGCConfiguration.cmake
index a170f4f43997..f00bcf3ad393 100644
--- a/cmake/Qt6QGCConfiguration.cmake
+++ b/cmake/Qt6QGCConfiguration.cmake
@@ -54,3 +54,7 @@ endif()
include(CMakePrintHelpers)
cmake_print_variables(QT_VERSION QT_MKSPEC QT_LIBRARY_HINTS)
+
+# if(ANDROID)
+ # set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
+# endif()
diff --git a/cmake/find-modules/ECMFindModuleHelpersStub.cmake b/cmake/find-modules/ECMFindModuleHelpersStub.cmake
new file mode 100644
index 000000000000..bb8c9a62fc6d
--- /dev/null
+++ b/cmake/find-modules/ECMFindModuleHelpersStub.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/../modules/ECMFindModuleHelpers.cmake)
diff --git a/cmake/find-modules/FindEGL.cmake b/cmake/find-modules/FindEGL.cmake
new file mode 100644
index 000000000000..747901b3a946
--- /dev/null
+++ b/cmake/find-modules/FindEGL.cmake
@@ -0,0 +1,151 @@
+# SPDX-FileCopyrightText: 2014 Alex Merry
+# SPDX-FileCopyrightText: 2014 Martin Gräßlin
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindEGL
+-------
+
+Try to find EGL.
+
+This will define the following variables:
+
+``EGL_FOUND``
+ True if (the requested version of) EGL is available
+``EGL_VERSION``
+ The version of EGL; note that this is the API version defined in the
+ headers, rather than the version of the implementation (eg: Mesa)
+``EGL_LIBRARIES``
+ This can be passed to target_link_libraries() instead of the ``EGL::EGL``
+ target
+``EGL_INCLUDE_DIRS``
+ This should be passed to target_include_directories() if the target is not
+ used for linking
+``EGL_DEFINITIONS``
+ This should be passed to target_compile_options() if the target is not
+ used for linking
+
+If ``EGL_FOUND`` is TRUE, it will also define the following imported target:
+
+``EGL::EGL``
+ The EGL library
+
+In general we recommend using the imported target, as it is easier to use.
+Bear in mind, however, that if the target is in the link interface of an
+exported library, it must be made available by the package config file.
+
+Since pre-1.0.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+include(CheckCXXSourceCompiles)
+include(CMakePushCheckState)
+
+ecm_find_package_version_check(EGL)
+
+# Use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+find_package(PkgConfig QUIET)
+pkg_check_modules(PKG_EGL QUIET egl)
+
+set(EGL_DEFINITIONS ${PKG_EGL_CFLAGS_OTHER})
+
+find_path(EGL_INCLUDE_DIR
+ NAMES
+ EGL/egl.h
+ HINTS
+ ${PKG_EGL_INCLUDE_DIRS}
+)
+find_library(EGL_LIBRARY
+ NAMES
+ EGL
+ libEGL
+ HINTS
+ ${PKG_EGL_LIBRARY_DIRS}
+)
+
+# NB: We do *not* use the version information from pkg-config, as that
+# is the implementation version (eg: the Mesa version)
+if(EGL_INCLUDE_DIR)
+ # egl.h has defines of the form EGL_VERSION_x_y for each supported
+ # version; so the header for EGL 1.1 will define EGL_VERSION_1_0 and
+ # EGL_VERSION_1_1. Finding the highest supported version involves
+ # finding all these defines and selecting the highest numbered.
+ file(READ "${EGL_INCLUDE_DIR}/EGL/egl.h" _EGL_header_contents)
+ string(REGEX MATCHALL
+ "[ \t]EGL_VERSION_[0-9_]+"
+ _EGL_version_lines
+ "${_EGL_header_contents}"
+ )
+ unset(_EGL_header_contents)
+ foreach(_EGL_version_line ${_EGL_version_lines})
+ string(REGEX REPLACE
+ "[ \t]EGL_VERSION_([0-9_]+)"
+ "\\1"
+ _version_candidate
+ "${_EGL_version_line}"
+ )
+ string(REPLACE "_" "." _version_candidate "${_version_candidate}")
+ if(NOT DEFINED EGL_VERSION OR EGL_VERSION VERSION_LESS _version_candidate)
+ set(EGL_VERSION "${_version_candidate}")
+ endif()
+ endforeach()
+ unset(_EGL_version_lines)
+endif()
+
+cmake_push_check_state(RESET)
+list(APPEND CMAKE_REQUIRED_LIBRARIES "${EGL_LIBRARY}")
+list(APPEND CMAKE_REQUIRED_INCLUDES "${EGL_INCLUDE_DIR}")
+
+check_cxx_source_compiles("
+#include
+
+int main(int argc, char *argv[]) {
+ EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0;
+ eglDestroyContext(dpy, ctx);
+}" HAVE_EGL)
+
+cmake_pop_check_state()
+
+set(required_vars EGL_INCLUDE_DIR HAVE_EGL)
+if(NOT EMSCRIPTEN)
+ list(APPEND required_vars EGL_LIBRARY)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(EGL
+ FOUND_VAR
+ EGL_FOUND
+ REQUIRED_VARS
+ ${required_vars}
+ VERSION_VAR
+ EGL_VERSION
+)
+
+if(EGL_FOUND AND NOT TARGET EGL::EGL)
+ if (EMSCRIPTEN)
+ add_library(EGL::EGL INTERFACE IMPORTED)
+ # Nothing further to be done, system include paths have headers and linkage is implicit.
+ else()
+ add_library(EGL::EGL UNKNOWN IMPORTED)
+ set_target_properties(EGL::EGL PROPERTIES
+ IMPORTED_LOCATION "${EGL_LIBRARY}"
+ INTERFACE_COMPILE_OPTIONS "${EGL_DEFINITIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${EGL_INCLUDE_DIR}"
+ )
+ endif()
+endif()
+
+mark_as_advanced(EGL_LIBRARY EGL_INCLUDE_DIR HAVE_EGL)
+
+# compatibility variables
+set(EGL_LIBRARIES ${EGL_LIBRARY})
+set(EGL_INCLUDE_DIRS ${EGL_INCLUDE_DIR})
+set(EGL_VERSION_STRING ${EGL_VERSION})
+
+include(FeatureSummary)
+set_package_properties(EGL PROPERTIES
+ URL "https://www.khronos.org/egl/"
+ DESCRIPTION "A platform-agnostic mechanism for creating rendering surfaces for use with other graphics libraries, such as OpenGL|ES and OpenVG."
+)
diff --git a/cmake/FindFFMPEG.cmake b/cmake/find-modules/FindFFMPEG.cmake
similarity index 100%
rename from cmake/FindFFMPEG.cmake
rename to cmake/find-modules/FindFFMPEG.cmake
diff --git a/cmake/find-modules/FindFFmpeg.cmake b/cmake/find-modules/FindFFmpeg.cmake
new file mode 100644
index 000000000000..27b49a2a5091
--- /dev/null
+++ b/cmake/find-modules/FindFFmpeg.cmake
@@ -0,0 +1,384 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+#.rst:
+# FindFFmpeg
+# ----------
+#
+# Try to find the required ffmpeg components (default: AVFORMAT, AVUTIL, AVCODEC)
+#
+# Next variables can be used to hint FFmpeg libs search:
+#
+# ::
+#
+# PC__LIBRARY_DIRS
+# PC_FFMPEG_LIBRARY_DIRS
+# PC__INCLUDE_DIRS
+# PC_FFMPEG_INCLUDE_DIRS
+#
+# Once done this will define
+#
+# ::
+#
+# FFMPEG_FOUND - System has the all required components.
+# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
+# FFMPEG_LIBRARIES - Link these to use the required FFmpeg components.
+# FFMPEG_LIBRARY_DIRS - Link directories
+# FFMPEG_DEFINITIONS - Compiler switches required for using the required FFmpeg components.
+#
+# For each of the components it will additionally set.
+#
+# ::
+#
+# AVCODEC
+# AVDEVICE
+# AVFORMAT
+# AVFILTER
+# AVUTIL
+# POSTPROC
+# SWSCALE
+#
+# the following variables will be defined
+#
+# ::
+#
+# _FOUND - System has
+# FFMPEG__FOUND - System has (as checked by FHSPA)
+# _INCLUDE_DIRS - Include directory necessary for using the headers
+# _LIBRARIES - Link these to use
+# _LIBRARY_DIRS - Link directories
+# _DEFINITIONS - Compiler switches required for using
+# _VERSION - The components version
+#
+# the following import targets is created
+#
+# ::
+#
+# FFmpeg::FFmpeg - for all components
+# FFmpeg:: - where in lower case (FFmpeg::avcodec) for each components
+#
+# Copyright (c) 2006, Matthias Kretz,
+# Copyright (c) 2008, Alexander Neundorf,
+# Copyright (c) 2011, Michael Jansen,
+# Copyright (c) 2017, Alexander Drozdov,
+#
+
+include(FindPackageHandleStandardArgs)
+
+# The default components were taken from a survey over other FindFFMPEG.cmake files
+if (NOT FFmpeg_FIND_COMPONENTS)
+ set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL)
+endif ()
+
+if (QT_DEPLOY_FFMPEG AND BUILD_SHARED_LIBS)
+ set(shared_libs_desired TRUE)
+endif()
+
+# finds FFmpeg libs, including symlinks, for the specified component.
+macro(find_shared_libs_for_component _component)
+ # the searching pattern is pretty rough but it seems to be sufficient to gather dynamic libs
+ get_filename_component(name_we ${${_component}_LIBRARY} NAME_WE)
+
+ if (WIN32)
+ get_filename_component(dir_name ${${_component}_LIBRARY_DIR} NAME)
+ if (${dir_name} STREQUAL "lib" AND EXISTS "${${_component}_LIBRARY_DIR}/../bin")
+ # llvm-mingv builds aux ffmpeg static libs like lib/libavutil.dll.a and cmake finds
+ # only them even though the folder bin/ contains proper *.dll and *.lib.
+
+ string(REGEX REPLACE "^lib" "" name_we "${name_we}")
+ set(shared_lib_pattern "../bin/${name_we}*${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ else()
+ set(shared_lib_pattern "${name_we}*${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ endif()
+
+ else()
+ set(shared_lib_pattern "${name_we}*${CMAKE_SHARED_LIBRARY_SUFFIX}*")
+ endif()
+
+ file(GLOB ${_component}_SHARED_LIBRARIES "${${_component}_LIBRARY_DIR}/${shared_lib_pattern}")
+endmacro()
+
+#
+### Macro: set_component_found
+#
+# Marks the given component as found if both *_LIBRARY_NAME AND *_INCLUDE_DIRS is present.
+#
+macro(set_component_found _component)
+ if (${_component}_LIBRARY_NAME AND ${_component}_INCLUDE_DIR)
+ # message(STATUS " - ${_component} found.")
+ set(${_component}_FOUND TRUE)
+ set(${CMAKE_FIND_PACKAGE_NAME}_${_component}_FOUND TRUE)
+ else ()
+ # message(STATUS " - ${_component} not found.")
+ endif ()
+endmacro()
+
+find_package(PkgConfig QUIET)
+if (NOT PKG_CONFIG_FOUND AND NOT FFMPEG_DIR)
+ set(FFMPEG_DIR "/usr/local")
+endif()
+#
+### Macro: find_component
+#
+# Checks for the given component by invoking pkgconfig and then looking up the libraries and
+# include directories.
+#
+macro(find_component _component _pkgconfig _library _header)
+
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ if (PKG_CONFIG_FOUND AND NOT FFMPEG_DIR)
+ pkg_check_modules(PC_${_component} ${_pkgconfig})
+ endif ()
+
+ if (FFMPEG_DIR OR FFMPEG_ROOT)
+ set(__find_ffmpeg_backup_root_dir "${CMAKE_FIND_ROOT_PATH}")
+ endif()
+
+ if(FFMPEG_DIR)
+ list(APPEND CMAKE_FIND_ROOT_PATH "${FFMPEG_DIR}")
+ endif()
+
+ if(FFMPEG_ROOT)
+ list(APPEND CMAKE_FIND_ROOT_PATH "${FFMPEG_ROOT}")
+ endif()
+
+ if (${_component}_INCLUDE_DIR AND NOT EXISTS ${${_component}_INCLUDE_DIR})
+ message(STATUS "Cached include dir ${${_component}_INCLUDE_DIR} doesn't exist")
+ unset(${_component}_INCLUDE_DIR CACHE)
+ endif()
+
+ find_path(${_component}_INCLUDE_DIR ${_header}
+ HINTS
+ ${PC_${_component}_INCLUDEDIR}
+ ${PC_${_component}_INCLUDE_DIRS}
+ ${PC_FFMPEG_INCLUDE_DIRS}
+ PATHS
+ ${FFMPEG_DIR}
+ PATH_SUFFIXES
+ ffmpeg include
+ )
+
+ if (shared_libs_desired AND NOT WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_SHARED_LIBRARY_SUFFIX};${CMAKE_STATIC_LIBRARY_SUFFIX}")
+ endif()
+
+ if (${_component}_LIBRARY AND NOT EXISTS ${${_component}_LIBRARY})
+ message(STATUS "Cached library ${${_component}_LIBRARY} doesn't exist")
+ unset(${_component}_LIBRARY CACHE)
+ endif()
+
+ find_library(${_component}_LIBRARY
+ NAMES ${PC_${_component}_LIBRARIES} ${_library}
+ HINTS
+ ${PC_${_component}_LIBDIR}
+ ${PC_${_component}_LIBRARY_DIRS}
+ ${PC_FFMPEG_LIBRARY_DIRS}
+ PATHS
+ ${FFMPEG_DIR}
+ PATH_SUFFIXES
+ lib bin
+ )
+
+ if(FFMPEG_DIR OR FFMPEG_ROOT)
+ set(CMAKE_FIND_ROOT_PATH "${__find_ffmpeg_backup_root_dir}")
+ endif()
+
+ if (${_component}_LIBRARY)
+ get_filename_component(${_component}_LIBRARY_DIR ${${_component}_LIBRARY} DIRECTORY)
+ get_filename_component(${_component}_LIBRARY_NAME ${${_component}_LIBRARY} NAME)
+
+ # On Windows, shared linking goes through 'integration' static libs, so we should look for shared ones anyway
+ # On Unix, we gather symlinks as well so that we could install them.
+ if (WIN32 OR ${${_component}_LIBRARY_NAME} MATCHES "\\${CMAKE_SHARED_LIBRARY_SUFFIX}$")
+ find_shared_libs_for_component(${_component})
+ endif()
+
+ endif()
+
+ set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER})
+ set_component_found(${_component})
+
+ mark_as_advanced(${_component}_LIBRARY)
+endmacro()
+
+# Clear the previously cached variables, because they are recomputed every time
+# the Find script is included.
+unset(FFMPEG_INCLUDE_DIRS)
+unset(FFMPEG_LIBRARIES)
+unset(FFMPEG_SHARED_LIBRARIES)
+unset(FFMPEG_DEFINITIONS)
+unset(FFMPEG_LIBRARY_DIRS)
+
+# Check for components.
+foreach (_component ${FFmpeg_FIND_COMPONENTS})
+ string(TOLOWER ${_component} library)
+ find_component(${_component} "lib${library}" ${library} "lib${library}/${library}.h")
+
+ if (${_component}_FOUND)
+ list(APPEND FFMPEG_LIBRARIES ${${_component}_LIBRARY_NAME})
+ list(APPEND FFMPEG_DEFINITIONS ${${_component}_DEFINITIONS})
+ list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIR})
+ list(APPEND FFMPEG_LIBRARY_DIRS ${${_component}_LIBRARY_DIR})
+
+ if (${_component}_SHARED_LIBRARIES)
+ list(APPEND FFMPEG_SHARED_LIBRARIES ${${_component}_SHARED_LIBRARIES})
+ list(APPEND FFMPEG_SHARED_COMPONENTS ${_component})
+ else()
+ list(APPEND FFMPEG_STATIC_COMPONENTS ${_component})
+ endif()
+
+ mark_as_advanced(${_component}_LIBRARY_NAME ${_component}_DEFINITIONS ${_component}_INCLUDE_DIR
+ ${_component}_LIBRARY_DIR ${_component}_SHARED_LIBRARIES)
+ endif()
+endforeach()
+
+if (NOT FFMPEG_SHARED_COMPONENTS AND (ANDROID OR LINUX))
+ set(ENABLE_DYNAMIC_RESOLVE_OPENSSL_SYMBOLS TRUE CACHE INTERNAL "")
+endif()
+
+set(ENABLE_DYNAMIC_RESOLVE_VAAPI_SYMBOLS ${LINUX} CACHE INTERNAL "")
+
+function(__try_add_dynamic_resolve_dependency dep added)
+ set(added TRUE PARENT_SCOPE)
+
+ if(ENABLE_DYNAMIC_RESOLVE_OPENSSL_SYMBOLS AND
+ (${dep} STREQUAL "ssl" OR ${dep} STREQUAL "crypto"))
+ set(DYNAMIC_RESOLVE_OPENSSL_SYMBOLS TRUE CACHE INTERNAL "")
+ elseif(ENABLE_DYNAMIC_RESOLVE_VAAPI_SYMBOLS AND ${dep} STREQUAL "va")
+ set(DYNAMIC_RESOLVE_VAAPI_SYMBOLS TRUE CACHE INTERNAL "")
+ elseif(ENABLE_DYNAMIC_RESOLVE_VAAPI_SYMBOLS AND ${dep} STREQUAL "va-drm")
+ set(DYNAMIC_RESOLVE_VA_DRM_SYMBOLS TRUE CACHE INTERNAL "")
+ elseif(ENABLE_DYNAMIC_RESOLVE_VAAPI_SYMBOLS AND ${dep} STREQUAL "va-x11")
+ set(DYNAMIC_RESOLVE_VA_X11_SYMBOLS TRUE CACHE INTERNAL "")
+ else()
+ set(added FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Function parses package config file to find the static library dependencies
+# and adds them to the target library.
+function(__ffmpeg_internal_set_dependencies lib)
+ set(PC_FILE ${FFMPEG_DIR}/lib/pkgconfig/lib${lib}.pc)
+ if(EXISTS ${PC_FILE})
+ file(READ ${PC_FILE} pcfile)
+
+ set(prefix_l "(^| )\\-l")
+ set(suffix_lib "\\.lib($| )")
+
+ string(REGEX REPLACE ".*Libs:([^\n\r]+).*" "\\1" out "${pcfile}")
+ string(REGEX MATCHALL "${prefix_l}[^ ]+" libs_dependency ${out})
+ string(REGEX MATCHALL "[^ ]+${suffix_lib}" libs_dependency_lib ${out})
+
+ string(REGEX REPLACE ".*Libs.private:([^\n\r]+).*" "\\1" out "${pcfile}")
+ string(REGEX MATCHALL "${prefix_l}[^ ]+" libs_private_dependency ${out})
+ string(REGEX MATCHALL "[^ ]+${suffix_lib}" libs_private_dependency_lib ${out})
+
+ list(APPEND deps_no_suffix ${libs_dependency} ${libs_private_dependency})
+ foreach(dependency ${deps_no_suffix})
+ string(REGEX REPLACE ${prefix_l} "" dependency ${dependency})
+ if(NOT ${lib} STREQUAL ${dependency})
+ __try_add_dynamic_resolve_dependency(${dependency} added)
+ if(NOT added)
+ target_link_libraries(FFmpeg::${lib} INTERFACE ${dependency})
+ endif()
+ endif()
+ endforeach()
+
+ list(APPEND deps_lib_suffix ${libs_dependency_lib} ${libs_private_dependency_lib})
+ foreach(dependency ${deps_lib_suffix})
+ string(REGEX REPLACE ${suffix_lib} "" dependency ${dependency})
+ target_link_libraries(FFmpeg::${lib} INTERFACE ${dependency})
+ endforeach()
+ endif()
+endfunction()
+
+# Check for cached results. If there are skip the costly part.
+#if (NOT FFMPEG_LIBRARIES)
+
+ # Check if the required components were found and add their stuff to the FFMPEG_* vars.
+
+
+ foreach (_component ${FFmpeg_FIND_COMPONENTS})
+ if (${_component}_FOUND)
+ string(TOLOWER ${_component} _lowerComponent)
+ if (NOT TARGET FFmpeg::${_lowerComponent})
+ add_library(FFmpeg::${_lowerComponent} INTERFACE IMPORTED)
+ set_target_properties(FFmpeg::${_lowerComponent} PROPERTIES
+ INTERFACE_COMPILE_OPTIONS "${${_component}_DEFINITIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES ${${_component}_INCLUDE_DIR}
+ INTERFACE_LINK_LIBRARIES "${${_component}_LIBRARY_NAME}"
+ INTERFACE_LINK_DIRECTORIES "${${_component}_LIBRARY_DIR}"
+ )
+ if(NOT ${_component}_SHARED_LIBRARIES)
+ __ffmpeg_internal_set_dependencies(${_lowerComponent})
+ endif()
+ target_link_libraries(FFmpeg::${_lowerComponent} INTERFACE "${${_component}_LIBRARY_NAME}")
+ if (UNIX AND NOT APPLE)
+ target_link_options(FFmpeg::${_lowerComponent} INTERFACE "-Wl,--exclude-libs=lib${_lowerComponent}")
+ endif ()
+ endif()
+ endif()
+ endforeach ()
+
+ # Build the include path with duplicates removed.
+ list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
+ list(REMOVE_DUPLICATES FFMPEG_LIBRARY_DIRS)
+ list(REMOVE_DUPLICATES FFMPEG_SHARED_LIBRARIES)
+
+ message(STATUS "FFmpeg shared libs: ${FFMPEG_SHARED_LIBRARIES}")
+
+ # cache the vars.
+ set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
+ set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
+ set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
+ set(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBRARY_DIRS} CACHE STRING "The FFmpeg library dirs." FORCE)
+ set(FFMPEG_SHARED_LIBRARIES ${FFMPEG_SHARED_LIBRARIES} CACHE STRING "The FFmpeg dynamic libraries." FORCE)
+
+ mark_as_advanced(FFMPEG_INCLUDE_DIRS
+ FFMPEG_LIBRARIES
+ FFMPEG_DEFINITIONS
+ FFMPEG_LIBRARY_DIRS
+ FFMPEG_SHARED_LIBRARIES
+ )
+# endif ()
+
+list(LENGTH FFMPEG_LIBRARY_DIRS DIRS_COUNT)
+if (${DIRS_COUNT} GREATER 1)
+ message(WARNING "One ffmpeg library dir is expected, found dirs: ${FFMPEG_LIBRARY_DIRS}")
+endif()
+
+if(FFMPEG_SHARED_COMPONENTS AND FFMPEG_STATIC_COMPONENTS)
+ message(WARNING
+ "Only static or shared components are expected\n"
+ " static components: ${FFMPEG_STATIC_COMPONENTS}\n"
+ " shared components: ${FFMPEG_SHARED_COMPONENTS}")
+endif()
+
+if (shared_libs_desired AND NOT FFMPEG_SHARED_COMPONENTS)
+ message(WARNING
+ "Shared FFmpeg libs are desired as QT_DEPLOY_FFMPEG=TRUE, but haven't been found!\n"
+ "Remove QT_DEPLOY_FFMPEG or set the proper path to shared FFmpeg via FFMPEG_DIR.")
+endif()
+
+if (NOT TARGET FFmpeg::FFmpeg)
+ add_library(FFmpeg INTERFACE)
+ set_target_properties(FFmpeg PROPERTIES
+ INTERFACE_COMPILE_OPTIONS "${FFMPEG_DEFINITIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIRS}"
+ INTERFACE_LINK_LIBRARIES "${FFMPEG_LIBRARIES}"
+ INTERFACE_LINK_DIRECTORIES "${FFMPEG_LIBRARY_DIRS}"
+ )
+ add_library(FFmpeg::FFmpeg ALIAS FFmpeg)
+endif()
+
+# Compile the list of required vars
+set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
+foreach (_component ${FFmpeg_FIND_COMPONENTS})
+ list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARY ${_component}_INCLUDE_DIR)
+endforeach ()
+
+# Give a nice error message if some of the required vars are missing.
+find_package_handle_standard_args(FFmpeg
+ REQUIRED_VARS ${_FFmpeg_REQUIRED_VARS}
+ HANDLE_COMPONENTS
+)
diff --git a/cmake/find-modules/FindGLIB2.cmake b/cmake/find-modules/FindGLIB2.cmake
new file mode 100644
index 000000000000..01d1c0cfe69a
--- /dev/null
+++ b/cmake/find-modules/FindGLIB2.cmake
@@ -0,0 +1,151 @@
+# SPDX-FileCopyrightText: 2008 Laurent Montel
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+
+#[=======================================================================[.rst:
+FindGLIB2
+---------
+
+Try to locate the GLib2 library.
+If found, this will define the following variables:
+
+``GLIB2_FOUND``
+ True if the GLib2 library is available
+``GLIB2_INCLUDE_DIRS``
+ The GLib2 include directories
+``GLIB2_LIBRARIES``
+ The GLib2 libraries for linking
+``GLIB2_INCLUDE_DIR``
+ Deprecated, use ``GLIB2_INCLUDE_DIRS``
+``GLIB2_LIBRARY``
+ Deprecated, use ``GLIB2_LIBRARIES``
+
+If ``GLIB2_FOUND`` is TRUE, it will also define the following
+imported target:
+
+``GLIB2::GLIB2``
+ The GLIB2 library
+``GLIB2::GTHREAD2``
+ The GThread2 library (since 6.7.0)
+``GLIB2::GOBJECT``
+ The GObject library (since 6.7.0)
+``GLIB2::GIO``
+ The GIO library (since 6.7.0)
+
+Since 5.41.0.
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_GLIB2 QUIET glib-2.0)
+
+find_path(GLIB2_INCLUDE_DIRS
+ NAMES glib.h
+ HINTS ${PC_GLIB2_INCLUDEDIR}
+ PATH_SUFFIXES glib-2.0)
+
+find_library(GLIB2_LIBRARIES
+ NAMES glib-2.0
+ HINTS ${PC_GLIB2_LIBDIR}
+)
+
+pkg_check_modules(PC_GTHREAD2 QUIET gthread-2.0)
+
+find_library(GTHREAD2_LIBRARIES
+ NAMES gthread-2.0
+ HINTS ${PC_GTHREAD2_LIBDIR}
+)
+
+pkg_check_modules(PC_GOBJECT QUIET gobject-2.0)
+
+find_path(GLIB2_GOBJECT_INCLUDE_DIRS
+ NAMES glib-object.h
+ HINTS ${PC_GOBJECT_INCLUDEDIR}
+ PATH_SUFFIXES glib-2.0)
+
+find_library(GLIB2_GOBJECT_LIBRARIES
+ NAMES gobject-2.0
+ HINTS ${PC_GOBJECT_LIBDIR}
+)
+
+pkg_check_modules(PC_GIO QUIET gio-2.0)
+
+find_path(GLIB2_GIO_INCLUDE_DIRS
+ NAMES gio/gio.h
+ HINTS ${PC_GIO_INCLUDEDIR}
+ PATH_SUFFIXES glib-2.0)
+
+find_library(GLIB2_GIO_LIBRARIES
+ NAMES gio-2.0
+ HINTS ${PC_GIO_LIBDIR}
+)
+
+# search the glibconfig.h include dir under the same root where the library is found
+get_filename_component(glib2LibDir "${GLIB2_LIBRARIES}" PATH)
+
+find_path(GLIB2_INTERNAL_INCLUDE_DIR glibconfig.h
+ PATH_SUFFIXES glib-2.0/include
+ HINTS ${PC_GLIB2_INCLUDEDIR} "${glib2LibDir}" ${CMAKE_SYSTEM_LIBRARY_PATH})
+
+# not sure if this include dir is optional or required
+# for now it is optional
+if(GLIB2_INTERNAL_INCLUDE_DIR)
+ list(APPEND GLIB2_INCLUDE_DIRS "${GLIB2_INTERNAL_INCLUDE_DIR}")
+ list(APPEND GLIB2_GOBJECT_INCLUDE_DIRS "${GLIB2_INTERNAL_INCLUDE_DIR}")
+ list(APPEND GLIB2_GIO_INCLUDE_DIRS "${GLIB2_INTERNAL_INCLUDE_DIR}")
+endif()
+
+# Deprecated synonyms
+set(GLIB2_INCLUDE_DIR "${GLIB2_INCLUDE_DIRS}")
+set(GLIB2_LIBRARY "${GLIB2_LIBRARIES}")
+set(GLIB2_GOBJECT_INCLUDE_DIR "${GLIB2_GOBJECT_INCLUDE_DIRS}")
+set(GLIB2_GOBJECT_LIBRARY "${GLIB2_GOBJECT_LIBRARIES}")
+set(GLIB2_GIO_INCLUDE_DIR "${GLIB2_GIO_INCLUDE_DIRS}")
+set(GLIB2_GIO_LIBRARY "${GLIB2_GIO_LIBRARIES}")
+
+if(GLIB2_GOBJECT_LIBRARIES AND GLIB2_GOBJECT_INCLUDE_DIRS)
+ set(GLIB2_GOBJECT_FOUND TRUE)
+endif()
+
+if(GLIB2_GIO_LIBRARIES AND GLIB2_GIO_INCLUDE_DIRS)
+ set(GLIB2_GIO_FOUND TRUE)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GLIB2
+ REQUIRED_VARS GLIB2_LIBRARIES GTHREAD2_LIBRARIES GLIB2_INCLUDE_DIRS
+ HANDLE_COMPONENTS)
+
+if(GLIB2_FOUND AND NOT TARGET GLIB2::GLIB2)
+ add_library(GLIB2::GLIB2 UNKNOWN IMPORTED)
+ set_target_properties(GLIB2::GLIB2 PROPERTIES
+ IMPORTED_LOCATION "${GLIB2_LIBRARIES}"
+ INTERFACE_LINK_LIBRARIES "${GTHREAD2_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_INCLUDE_DIRS}")
+endif()
+
+if(GLIB2_GOBJECT_FOUND AND NOT TARGET GLIB2::GOBJECT)
+ add_library(GLIB2::GOBJECT UNKNOWN IMPORTED)
+ set_target_properties(GLIB2::GOBJECT PROPERTIES
+ IMPORTED_LOCATION "${GLIB2_GOBJECT_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GOBJECT_INCLUDE_DIRS}")
+endif()
+
+if(GLIB2_GIO_FOUND AND NOT TARGET GLIB2::GIO)
+ add_library(GLIB2::GIO UNKNOWN IMPORTED)
+ set_target_properties(GLIB2::GIO PROPERTIES
+ IMPORTED_LOCATION "${GLIB2_GIO_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GIO_INCLUDE_DIRS}")
+endif()
+
+mark_as_advanced(GLIB2_INCLUDE_DIRS GLIB2_INCLUDE_DIR
+ GLIB2_LIBRARIES GLIB2_LIBRARY
+ GLIB2_GOBJECT_INCLUDE_DIRS GLIB2_GOBJECT_INCLUDE_DIR
+ GLIB2_GOBJECT_LIBRARIES GLIB2_GOBJECT_LIBRARY
+ GLIB2_GIO_INCLUDE_DIRS GLIB2_GIO_INCLUDE_DIR
+ GLIB2_GIO_LIBRARIES GLIB2_GIO_LIBRARY)
+
+include(FeatureSummary)
+set_package_properties(GLIB2 PROPERTIES
+ URL "https://wiki.gnome.org/Projects/GLib"
+ DESCRIPTION "Event loop and utility library")
diff --git a/cmake/FindGStreamer.cmake b/cmake/find-modules/FindGStreamer.cmake
similarity index 61%
rename from cmake/FindGStreamer.cmake
rename to cmake/find-modules/FindGStreamer.cmake
index ed0b86f947b7..1e9a91722f19 100644
--- a/cmake/FindGStreamer.cmake
+++ b/cmake/find-modules/FindGStreamer.cmake
@@ -1,35 +1,6 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-# FindGStreamer
-# ---------
-#
-# Locate the gstreamer-1.0 library and some of its plugins.
-# Defines the following imported target:
-#
-# ``GStreamer::GStreamer``
-# If the gstreamer-1.0 library is available and target GStreamer::Base,
-# GStreamer::Audio, GStreamer::Video, GStreamer::Pbutils and
-# GStreamer::Allocators exist
-#
-# If target GStreamer::GStreamer exists, the following targets may be defined:
-#
-# ``GStreamer::App``
-# If the gstapp-1.0 library is available and target GStreamer::GStreamer exists
-# ``GStreamer::Photography``
-# If the gstphotography-1.0 library is available and target GStreamer::GStreamer exists
-# ``GStreamer::Gl``
-# If the gstgl-1.0 library is available and target GStreamer::GStreamer exists
-#
-
-################################################################################
-
-if(ANDROID)
- set(QGC_GST_STATIC_BUILD ON)
- list(APPEND PKG_CONFIG_ARGN --static)
-endif()
-
if(ANDROID OR IOS)
+ set(QGC_GST_STATIC_BUILD ON CACHE BOOL "Build GST Statically")
+
if(DEFINED ENV{GST_VERSION})
set(QGC_GST_TARGET_VERSION $ENV{GST_VERSION} CACHE STRING "Environment Provided GStreamer Version")
else()
@@ -37,6 +8,10 @@ if(ANDROID OR IOS)
endif()
endif()
+if(QGC_GST_STATIC_BUILD)
+ list(APPEND PKG_CONFIG_ARGN --static)
+endif()
+
################################################################################
# NOTE: CMP0144 in regards to GSTREAMER_ROOT
@@ -52,12 +27,8 @@ if(WIN32)
find_program(PKG_CONFIG_PROGRAM pkg-config PATHS ${GSTREAMER_PREFIX}/bin)
if(PKG_CONFIG_PROGRAM)
set(PKG_CONFIG_EXECUTABLE ${PKG_CONFIG_PROGRAM})
- cmake_print_variables(PKG_CONFIG_EXECUTABLE)
endif()
set(ENV{PKG_CONFIG_PATH} "${GSTREAMER_PREFIX}/lib/pkgconfig;${GSTREAMER_PREFIX}/lib/gstreamer-1.0/pkgconfig;$ENV{PKG_CONFIG_PATH}")
- # cmake_path(CONVERT "${GSTREAMER_PREFIX}/lib/pkgconfig;${GSTREAMER_PREFIX}/lib/gstreamer-1.0/pkgconfig;$ENV{PKG_CONFIG_PATH}" TO_NATIVE_PATH_LIST PKG_CONFIG_PATH NORMALIZE)
- # cmake_print_variables(PKG_CONFIG_PATH)
- # set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}")
cmake_path(CONVERT "${GSTREAMER_PREFIX}" TO_CMAKE_PATH_LIST PREFIX_PATH NORMALIZE)
cmake_path(CONVERT "${GSTREAMER_PREFIX}/lib" TO_CMAKE_PATH_LIST LIBDIR_PATH NORMALIZE)
cmake_path(CONVERT "${GSTREAMER_PREFIX}/include" TO_CMAKE_PATH_LIST INCLUDE_PATH NORMALIZE)
@@ -67,7 +38,6 @@ if(WIN32)
--define-variable=libdir=${LIBDIR_PATH}
--define-variable=includedir=${INCLUDE_PATH}
)
- cmake_print_variables(PKG_CONFIG_ARGN)
elseif(MACOS)
set(GSTREAMER_PREFIX "/Library/Frameworks/GStreamer.framework")
set(ENV{PKG_CONFIG_PATH} "${GSTREAMER_PREFIX}/Versions/Current/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}")
@@ -75,9 +45,10 @@ elseif(LINUX)
set(GSTREAMER_PREFIX "/usr")
set(ENV{PKG_CONFIG_PATH} "${GSTREAMER_PREFIX}/lib/pkgconfig:${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu/pkgconfig:$ENV{PKG_CONFIG_PATH}")
elseif(IOS)
- set(GSTREAMER_PREFIX "~/Library/Developer/GStreamer/iPhone.sdk/GStreamer.framework")
if(DEFINED ENV{GSTREAMER_PREFIX_IOS} AND EXISTS $ENV{GSTREAMER_PREFIX_IOS})
set(GSTREAMER_PREFIX_IOS $ENV{GSTREAMER_PREFIX_IOS})
+ elseif(EXISTS "~/Library/Developer/GStreamer/iPhone.sdk/GStreamer.framework")
+ set(GSTREAMER_PREFIX_IOS "~/Library/Developer/GStreamer/iPhone.sdk/GStreamer.framework")
else()
FetchContent_Declare(gstreamer
URL "https://gstreamer.freedesktop.org/data/pkg/ios/${QGC_GST_TARGET_VERSION}/gstreamer-1.0-devel-${QGC_GST_TARGET_VERSION}-ios-universal.pkg"
@@ -86,18 +57,26 @@ elseif(IOS)
FetchContent_MakeAvailable(gstreamer)
set(GSTREAMER_PREFIX_IOS ${gstreamer_SOURCE_DIR})
endif()
- # TODO: set(GSTREAMER_PREFIX ${GSTREAMER_PREFIX_IOS}/)
+ set(GSTREAMER_PREFIX ${GSTREAMER_PREFIX_IOS})
elseif(ANDROID)
set(GSTREAMER_PREFIX_ANDROID)
if(DEFINED ENV{GSTREAMER_PREFIX_ANDROID} AND EXISTS $ENV{GSTREAMER_PREFIX_ANDROID})
set(GSTREAMER_PREFIX_ANDROID $ENV{GSTREAMER_PREFIX_ANDROID})
else()
- FetchContent_Declare(gstreamer
- URL "https://gstreamer.freedesktop.org/data/pkg/android/${QGC_GST_TARGET_VERSION}/gstreamer-1.0-android-universal-${QGC_GST_TARGET_VERSION}.tar.xz"
- DOWNLOAD_EXTRACT_TIMESTAMP true
- )
- FetchContent_MakeAvailable(gstreamer)
- set(GSTREAMER_PREFIX_ANDROID ${gstreamer_SOURCE_DIR})
+ set(GSTREAMER_ARCHIVE "gstreamer-1.0-android-universal-${QGC_GST_TARGET_VERSION}.tar.xz")
+ set(GSTREAMER_URL "https://gstreamer.freedesktop.org/data/pkg/android/${QGC_GST_TARGET_VERSION}/${GSTREAMER_ARCHIVE}")
+ set(GSTREAMER_TARBALL "${CMAKE_BINARY_DIR}/_deps/gstreamer/${GSTREAMER_ARCHIVE}")
+ set(GSTREAMER_INSTALL_DIR "${CMAKE_BINARY_DIR}/_deps/gstreamer/install/gstreamer")
+ if(NOT EXISTS ${GSTREAMER_TARBALL})
+ message(STATUS "Downloading GStreamer from ${GSTREAMER_URL}")
+ file(DOWNLOAD ${GSTREAMER_URL} ${GSTREAMER_TARBALL} SHOW_PROGRESS)
+ endif()
+ if(NOT EXISTS ${GSTREAMER_INSTALL_DIR})
+ message(STATUS "Extracting GStreamer to ${GSTREAMER_INSTALL_DIR}")
+ file(MAKE_DIRECTORY ${GSTREAMER_INSTALL_DIR})
+ file(ARCHIVE_EXTRACT INPUT ${GSTREAMER_TARBALL} DESTINATION ${GSTREAMER_INSTALL_DIR})
+ endif()
+ set(GSTREAMER_PREFIX_ANDROID ${GSTREAMER_INSTALL_DIR})
endif()
if(${CMAKE_ANDROID_ARCH_ABI} STREQUAL armeabi-v7a)
set(GSTREAMER_PREFIX ${GSTREAMER_PREFIX_ANDROID}/armv7)
@@ -108,24 +87,19 @@ elseif(ANDROID)
elseif(${CMAKE_ANDROID_ARCH_ABI} STREQUAL x86_64)
set(GSTREAMER_PREFIX ${GSTREAMER_PREFIX_ANDROID}/x86_64)
endif()
- set(ENV{PKG_CONFIG_PATH} "${GSTREAMER_PREFIX}/lib/pkgconfig:${GSTREAMER_PREFIX}/lib/gstreamer-1.0/pkgconfig:$ENV{PKG_CONFIG_PATH}")
+ set(ENV{PKG_CONFIG_PATH} "")
set(ENV{PKG_CONFIG_LIBDIR} "${GSTREAMER_PREFIX}/lib/pkgconfig:${GSTREAMER_PREFIX}/lib/gstreamer-1.0/pkgconfig")
- # set(ENV{PKG_CONFIG_SYSROOT_DIR} "${GSTREAMER_PREFIX}")
- message(STATUS "PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH}")
- # message(STATUS "PKG_CONFIG_SYSROOT_DIR $ENV{PKG_CONFIG_SYSROOT_DIR}")
list(APPEND PKG_CONFIG_ARGN
--dont-define-prefix
--define-variable=prefix=${GSTREAMER_PREFIX}
--define-variable=libdir=${GSTREAMER_PREFIX}/lib
--define-variable=includedir=${GSTREAMER_PREFIX}/include
)
- cmake_print_variables(PKG_CONFIG_ARGN)
if(CMAKE_HOST_WIN32)
find_program(PKG_CONFIG_PROGRAM pkg-config PATHS ${GSTREAMER_PREFIX}/share/gst-android/ndk-build/tools/windows)
if(PKG_CONFIG_PROGRAM)
set(PKG_CONFIG_EXECUTABLE ${PKG_CONFIG_PROGRAM})
- cmake_print_variables(PKG_CONFIG_EXECUTABLE)
endif()
endif()
endif()
@@ -140,6 +114,10 @@ find_dependency(GObject)
set(GStreamer_VERSION ${QGC_GST_TARGET_VERSION})
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
+ message(STATUS "PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH}")
+ message(STATUS "PKG_CONFIG_LIBDIR $ENV{PKG_CONFIG_LIBDIR}")
+ # message(STATUS "PKG_CONFIG_SYSROOT_DIR $ENV{PKG_CONFIG_SYSROOT_DIR}")
+ cmake_print_variables(PKG_CONFIG_EXECUTABLE PKG_CONFIG_ARGN)
pkg_check_modules(GStreamer gstreamer-1.0)
else()
find_file(GStreamer_VERSION_HEADER
@@ -172,6 +150,8 @@ else()
endif()
cmake_print_variables(GStreamer_VERSION)
+################################################################################
+
function(find_gstreamer_component component prefix header library)
if(NOT TARGET GStreamer::${component})
string(TOUPPER ${component} upper)
@@ -336,18 +316,71 @@ foreach(component ${GStreamer_FIND_COMPONENTS})
endif()
elseif (${component} STREQUAL "X11")
find_gstreamer_component(X11 gstreamer-gl-x11-1.0 gst/gl/x11/x11.h x11-xcb)
- if(TARGET GStreamer::X11 AND TARGET GStreamer::Gl)
- target_link_libraries(GStreamer::X11 INTERFACE GStreamer::Gl)
+ if(TARGET GStreamer::X11)
+ if(GStreamer::Gl)
+ target_link_libraries(GStreamer::X11 INTERFACE GStreamer::Gl)
+ endif()
+ find_package(X11)
+ if(X11_FOUND)
+ target_link_libraries(GStreamer::X11 INTERFACE X11::X11)
+ endif()
+ find_package(XCB COMPONENTS XCB GLX)
+ if(XCB_FOUND)
+ target_link_libraries(GStreamer::X11 INTERFACE XCB::XCB XCB::GLX)
+ endif()
+ find_package(X11_XCB)
+ if(X11_XCB_FOUND)
+ target_link_libraries(GStreamer::X11 INTERFACE X11::XCB)
+ endif()
endif()
elseif (${component} STREQUAL "EGL")
find_gstreamer_component(EGL gstreamer-gl-egl-1.0 gst/gl/egl/egl.h egl)
- if(TARGET GStreamer::EGL AND TARGET GStreamer::Gl)
- target_link_libraries(GStreamer::EGL INTERFACE GStreamer::Gl)
+ if(TARGET GStreamer::EGL)
+ if(TARGET GStreamer::Gl)
+ target_link_libraries(GStreamer::EGL INTERFACE GStreamer::Gl)
+ endif()
+ find_package(EGL)
+ if(EGL_FOUND)
+ target_link_libraries(GStreamer::EGL INTERFACE EGL::EGL)
+ endif()
endif()
elseif (${component} STREQUAL "Wayland")
find_gstreamer_component(Wayland gstreamer-gl-wayland-1.0 gst/gl/wayland/wayland.h wayland-egl)
- if(TARGET GStreamer::Wayland AND TARGET GStreamer::Gl)
- target_link_libraries(GStreamer::Wayland INTERFACE GStreamer::Gl)
+ if(TARGET GStreamer::Wayland)
+ if(TARGET GStreamer::Gl)
+ target_link_libraries(GStreamer::Wayland INTERFACE GStreamer::Gl)
+ endif()
+ find_package(Wayland COMPONENTS Client Cursor Egl)
+ if(Wayland_FOUND)
+ target_link_libraries(GStreamer::Wayland INTERFACE Wayland::Client Wayland::Cursor Wayland::Egl)
+ endif()
+ find_package(WaylandProtocols)
+ if(WaylandProtocols_FOUND)
+ # WaylandProtocols_DATADIR
+ endif()
+ find_package(WaylandScanner)
+ if(WaylandScanner_FOUND)
+ # target_link_libraries(GStreamer::Wayland PUBLIC Wayland::Scanner)
+ endif()
+ find_package(Qt6 COMPONENTS WaylandClient)
+ if(Qt6WaylandClient_FOUND)
+ target_link_libraries(GStreamer::Wayland INTERFACE Qt6::WaylandClient)
+ endif()
+ endif()
+ elseif (${component} STREQUAL "PluginsBase")
+ find_gstreamer_component(PluginsBase gstreamer-plugins-base-1.0 gst/gst.h )
+ if(TARGET GStreamer::PluginsBase AND TARGET GStreamer::Core)
+ target_link_libraries(GStreamer::PluginsBase INTERFACE GStreamer::Core)
+ endif()
+ elseif (${component} STREQUAL "PluginsGood")
+ find_gstreamer_component(PluginsGood gstreamer-plugins-good-1.0 gst/gst.h )
+ if(TARGET GStreamer::PluginsGood AND TARGET GStreamer::Base)
+ target_link_libraries(GStreamer::PluginsGood INTERFACE GStreamer::Base)
+ endif()
+ elseif (${component} STREQUAL "PluginsBad")
+ find_gstreamer_component(PluginsBad gstreamer-plugins-bad-1.0 gst/gst.h )
+ if(TARGET GStreamer::PluginsBad AND TARGET GStreamer::PluginsGood)
+ target_link_libraries(GStreamer::PluginsBad INTERFACE GStreamer::PluginsGood)
endif()
else()
message(WARNING "FindGStreamer.cmake: Invalid Gstreamer component \"${component}\" requested")
@@ -356,6 +389,19 @@ endforeach()
################################################################################
+if(TARGET PkgConfig::PC_GSTREAMER_GL)
+ get_target_property(_qt_incs PkgConfig::PC_GSTREAMER_GL INTERFACE_INCLUDE_DIRECTORIES)
+ set(__qt_fixed_incs)
+ foreach(path IN LISTS _qt_incs)
+ if(IS_DIRECTORY "${path}")
+ list(APPEND __qt_fixed_incs "${path}")
+ endif()
+ endforeach()
+ set_property(TARGET PkgConfig::PC_GSTREAMER_GL PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${__qt_fixed_incs}")
+endif()
+
+################################################################################
+
# Create target GStreamer::GStreamer
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GStreamer
@@ -375,19 +421,200 @@ if(GStreamer_FOUND AND NOT TARGET GStreamer::GStreamer)
GStreamer::Video
GStreamer::Gl
)
- set_target_properties(GStreamer::GStreamer PROPERTIES VERSION ${GStreamer_Core_VERSION})
- set(GStreamer_VERSION ${GStreamer_Core_VERSION})
+ set_target_properties(GStreamer::GStreamer PROPERTIES VERSION ${GStreamer_VERSION})
endif()
-if(TARGET PkgConfig::PC_GSTREAMER_GL)
- get_target_property(_qt_incs PkgConfig::PC_GSTREAMER_GL INTERFACE_INCLUDE_DIRECTORIES)
- set(__qt_fixed_incs)
- foreach(path IN LISTS _qt_incs)
- if(IS_DIRECTORY "${path}")
- list(APPEND __qt_fixed_incs "${path}")
+################################################################################
+
+set(GST_TARGET_PLUGINS
+ gstcoreelements
+ gstisomp4
+ gstlibav
+ gstmatroska
+ gstmpegtsdemux
+ gstopengl
+ gstplayback
+ gstrtp
+ gstrtpmanager
+ gstrtsp
+ gstsdpelem
+ gsttcp
+ gstudp
+ gstvideoparsersbad
+ gstx264
+ gstqml6
+ gstasf
+ # gstva
+)
+if(ANDROID)
+ list(APPEND GST_TARGET_PLUGINS gstandroidmedia)
+elseif(IOS)
+ list(APPEND GST_TARGET_PLUGINS gstapplemedia)
+endif()
+
+find_package(PkgConfig QUIET)
+if(PkgConfig_FOUND)
+ pkg_check_modules(GST_PLUGINS IMPORTED_TARGET ${GST_TARGET_PLUGINS})
+ if(GST_PLUGINS_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE PkgConfig::GST_PLUGINS)
+ if(WIN32)
+ # install(FILES ${GST_PLUGINS_LIBRARIES} DESTINATION ${CMAKE_INSTALL_BINDIR})
+ elseif(LINUX)
+ # install(FILES ${GST_PLUGINS_LIBRARIES} DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ endif()
+ endif()
+
+ pkg_check_modules(GSTREAMER_PLUGINS_BASE IMPORTED_TARGET gstreamer-plugins-base-1.0)
+ if(GSTREAMER_PLUGINS_BASE_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE PkgConfig::GSTREAMER_PLUGINS_BASE)
+ endif()
+
+ pkg_check_modules(GSTREAMER_PLUGINS_GOOD IMPORTED_TARGET gstreamer-plugins-good-1.0)
+ if(GSTREAMER_PLUGINS_GOOD)
+ target_link_libraries(GStreamer::GStreamer INTERFACE PkgConfig::GSTREAMER_PLUGINS_GOOD)
+ endif()
+
+ pkg_check_modules(GSTREAMER_PLUGINS_BAD IMPORTED_TARGET gstreamer-plugins-bad-1.0)
+ if(GSTREAMER_PLUGINS_BAD)
+ target_link_libraries(GStreamer::GStreamer INTERFACE PkgConfig::GSTREAMER_PLUGINS_BAD)
+ endif()
+endif()
+
+if(NOT GST_PLUGINS_FOUND)
+ set(GST_DEPENDENCIES
+ glib-2.0
+ gio
+ gobject-2.0
+ gmodule-no-export-2.0
+ zlib
+ drm
+ graphene-1.0
+ opus
+ ffi
+ dl
+ m
+ )
+ list(APPEND GST_TARGET_PLUGINS ${GST_DEPENDENCIES})
+
+ foreach(plugin IN LISTS GST_TARGET_PLUGINS)
+ find_library(GStreamer_${plugin}_LIBRARY
+ NAMES ${plugin}
+ PATHS
+ ${GSTREAMER_PREFIX}/lib
+ ${GSTREAMER_PREFIX}/lib/gstreamer-1.0
+ ${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu
+ ${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu/gstreamer-1.0
+ ${GSTREAMER_PREFIX}/Versions/Current/lib
+ ${GSTREAMER_PREFIX}/Versions/Current/lib/gstreamer-1.0
+ )
+ find_path(GStreamer_${plugin}_INCLUDE_DIR
+ NAMES ${header}
+ PATH_SUFFIXES gstreamer-1.0
+ PATHS ${GSTREAMER_PREFIX}/include
+ )
+ if(GStreamer_${plugin}_LIBRARY AND GStreamer_${plugin}_INCLUDE_DIR)
+ cmake_print_variables(plugin)
+ target_link_libraries(GStreamer::GStreamer INTERFACE ${GStreamer_${plugin}_LIBRARY})
+ target_include_directories(GStreamer::GStreamer INTERFACE ${GStreamer_${plugin}_INCLUDE_DIR})
+ if(WIN32)
+ # install(FILES ${GStreamer_${plugin}_LIBRARY} DESTINATION ${CMAKE_INSTALL_BINDIR})
+ elseif(LINUX)
+ # install(FILES ${GStreamer_${plugin}_LIBRARY} DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ endif()
endif()
endforeach()
- set_property(TARGET PkgConfig::PC_GSTREAMER_GL PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${__qt_fixed_incs}")
+
+ find_package(OpenGL)
+ if(OpenGL_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE OpenGL::GL)
+ endif()
+
+ find_package(GLESv2)
+ if(GLESv2_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE GLESv2::GLESv2)
+ endif()
+
+ find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL OPTIONAL_COMPONENTS AVDEVICE AVFILTER POSTPROC SWSCALE)
+ if(FFMPEG_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE FFmpeg::FFmpeg)
+ endif()
+
+ find_package(BZip2)
+ if(BZIP2_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE BZip2::BZip2)
+ endif()
+
+ find_package(JPEG)
+ if(JPEG_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE JPEG::JPEG)
+ endif()
+
+ find_package(PNG)
+ if(PNG_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE PNG::PNG)
+ endif()
+
+ find_package(Intl)
+ if(Intl_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE Intl::Intl)
+ endif()
+
+ find_package(Iconv)
+ if(Iconv_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE Iconv::Iconv)
+ endif()
+
+ find_package(Threads)
+ if(Threads_FOUND)
+ target_link_libraries(GStreamer::GStreamer INTERFACE Threads::Threads)
+ endif()
+endif()
+
+if(ANDROID)
+ target_link_options(GStreamer::GStreamer INTERFACE "-Wl,-Bsymbolic")
+endif()
+
+if(QGC_GST_STATIC_BUILD)
+ target_compile_definitions(GStreamer::GStreamer INTERFACE QGC_GST_STATIC_BUILD)
+endif()
+
+if(ANDROID)
+ # find_path(GStreamer_${component}_INCLUDE_DIR
+ # NAMES ${header}
+ # PATH_SUFFIXES gstreamer-1.0
+ # PATHS ${GSTREAMER_PREFIX}/include
+ # )
+ target_include_directories(GStreamer::GStreamer
+ INTERFACE
+ ${GSTREAMER_PREFIX}/include/gstreamer-1.0
+ ${GSTREAMER_PREFIX}/include/glib-2.0
+ ${GSTREAMER_PREFIX}/lib/glib-2.0/include
+ ${GSTREAMER_PREFIX}/lib/graphene-1.0/include
+ ${GSTREAMER_PREFIX}/lib/gstreamer-1.0/include
+ ${GSTREAMER_PREFIX}/include
+ )
endif()
################################################################################
+
+# Use Latest Revisions for each minor version: 1.16.3, 1.18.6, 1.20.7, 1.22.12, 1.24.7
+string(REPLACE "." ";" GST_VERSION_LIST ${GStreamer_VERSION})
+list(GET GST_VERSION_LIST 0 GST_VERSION_MAJOR)
+list(GET GST_VERSION_LIST 1 GST_VERSION_MINOR)
+list(GET GST_VERSION_LIST 2 GST_VERSION_PATCH)
+cmake_print_variables(GST_VERSION_MAJOR GST_VERSION_MINOR GST_VERSION_PATCH)
+
+if(GST_VERSION_MINOR EQUAL 16)
+ set(GST_VERSION_PATCH 3)
+elseif(GST_VERSION_MINOR EQUAL 18)
+ set(GST_VERSION_PATCH 6)
+elseif(GST_VERSION_MINOR EQUAL 20)
+ set(GST_VERSION_PATCH 7)
+elseif(GST_VERSION_MINOR EQUAL 22)
+ set(GST_VERSION_PATCH 12)
+elseif(GST_VERSION_MINOR EQUAL 24)
+ set(GST_VERSION_PATCH 7)
+endif()
+
+set(GST_PLUGINS_VERSION ${GST_VERSION_MAJOR}.${GST_VERSION_MINOR}.${GST_VERSION_PATCH})
+cmake_print_variables(GST_PLUGINS_VERSION)
diff --git a/cmake/FindGeographicLib.cmake b/cmake/find-modules/FindGeographicLib.cmake
similarity index 100%
rename from cmake/FindGeographicLib.cmake
rename to cmake/find-modules/FindGeographicLib.cmake
diff --git a/cmake/find-modules/FindLibExiv2.cmake b/cmake/find-modules/FindLibExiv2.cmake
new file mode 100644
index 000000000000..83e1d6b7907f
--- /dev/null
+++ b/cmake/find-modules/FindLibExiv2.cmake
@@ -0,0 +1,102 @@
+# SPDX-FileCopyrightText: 2018 Christophe Giboudeaux
+# SPDX-FileCopyrightText: 2010 Alexander Neundorf
+# SPDX-FileCopyrightText: 2008 Gilles Caulier
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindLibExiv2
+------------
+
+Try to find the Exiv2 library.
+
+This will define the following variables:
+
+``LibExiv2_FOUND``
+ True if (the requested version of) Exiv2 is available
+
+``LibExiv2_VERSION``
+ The version of Exiv2
+
+``LibExiv2_INCLUDE_DIRS``
+ The include dirs of Exiv2 for use with target_include_directories()
+
+``LibExiv2_LIBRARIES``
+ The Exiv2 library for use with target_link_libraries().
+ This can be passed to target_link_libraries() instead of
+ the ``LibExiv2::LibExiv2`` target
+
+If ``LibExiv2_FOUND`` is TRUE, it will also define the following imported
+target:
+
+``LibExiv2::LibExiv2``
+ The Exiv2 library
+
+In general we recommend using the imported target, as it is easier to use.
+Bear in mind, however, that if the target is in the link interface of an
+exported library, it must be made available by the package config file.
+
+Since 5.53.0.
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_EXIV2 QUIET exiv2)
+
+find_path(LibExiv2_INCLUDE_DIRS NAMES exiv2/exif.hpp
+ HINTS ${PC_EXIV2_INCLUDEDIR}
+)
+
+find_library(LibExiv2_LIBRARIES NAMES exiv2 libexiv2
+ HINTS ${PC_EXIV2_LIBRARY_DIRS}
+)
+
+set(LibExiv2_VERSION ${PC_EXIV2_VERSION})
+
+if(NOT LibExiv2_VERSION AND DEFINED LibExiv2_INCLUDE_DIRS)
+ # With exiv >= 0.27, the version #defines are in exv_conf.h instead of version.hpp
+ foreach(_exiv2_version_file "version.hpp" "exv_conf.h")
+ if(EXISTS "${LibExiv2_INCLUDE_DIRS}/exiv2/${_exiv2_version_file}")
+ file(READ "${LibExiv2_INCLUDE_DIRS}/exiv2/${_exiv2_version_file}" _exiv_version_file_content)
+ string(REGEX MATCH "#define EXIV2_MAJOR_VERSION[ ]+\\([0-9]+U?\\)" EXIV2_MAJOR_VERSION_MATCH ${_exiv_version_file_content})
+ string(REGEX MATCH "#define EXIV2_MINOR_VERSION[ ]+\\([0-9]+U?\\)" EXIV2_MINOR_VERSION_MATCH ${_exiv_version_file_content})
+ string(REGEX MATCH "#define EXIV2_PATCH_VERSION[ ]+\\([0-9]+U?\\)" EXIV2_PATCH_VERSION_MATCH ${_exiv_version_file_content})
+ if(EXIV2_MAJOR_VERSION_MATCH)
+ string(REGEX REPLACE ".*_MAJOR_VERSION[ ]+\\(([0-9]*)U?\\)" "\\1" EXIV2_MAJOR_VERSION ${EXIV2_MAJOR_VERSION_MATCH})
+ string(REGEX REPLACE ".*_MINOR_VERSION[ ]+\\(([0-9]*)U?\\)" "\\1" EXIV2_MINOR_VERSION ${EXIV2_MINOR_VERSION_MATCH})
+ string(REGEX REPLACE ".*_PATCH_VERSION[ ]+\\(([0-9]*)U?\\)" "\\1" EXIV2_PATCH_VERSION ${EXIV2_PATCH_VERSION_MATCH})
+ endif()
+ endif()
+ endforeach()
+
+ set(LibExiv2_VERSION "${EXIV2_MAJOR_VERSION}.${EXIV2_MINOR_VERSION}.${EXIV2_PATCH_VERSION}")
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibExiv2
+ FOUND_VAR LibExiv2_FOUND
+ REQUIRED_VARS LibExiv2_LIBRARIES LibExiv2_INCLUDE_DIRS
+ VERSION_VAR LibExiv2_VERSION
+)
+
+mark_as_advanced(LibExiv2_INCLUDE_DIRS LibExiv2_LIBRARIES)
+
+if(LibExiv2_FOUND AND NOT TARGET LibExiv2::LibExiv2)
+ add_library(LibExiv2::LibExiv2 UNKNOWN IMPORTED)
+ set_target_properties(LibExiv2::LibExiv2 PROPERTIES
+ IMPORTED_LOCATION "${LibExiv2_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibExiv2_INCLUDE_DIRS}"
+ )
+ if (LibExiv2_VERSION VERSION_LESS 0.28.0)
+ # exiv2 0.27 or older still uses std::auto_ptr, which is no longer available
+ # by default when using newer C++ versions
+ set_target_properties(LibExiv2::LibExiv2 PROPERTIES
+ INTERFACE_COMPILE_DEFINITIONS "_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR=1;_HAS_AUTO_PTR_ETC=1"
+ )
+ endif()
+endif()
+
+include(FeatureSummary)
+set_package_properties(LibExiv2 PROPERTIES
+ URL "https://www.exiv2.org"
+ DESCRIPTION "Image metadata support"
+)
diff --git a/cmake/find-modules/FindQtWaylandScanner.cmake b/cmake/find-modules/FindQtWaylandScanner.cmake
new file mode 100644
index 000000000000..1a73b80facda
--- /dev/null
+++ b/cmake/find-modules/FindQtWaylandScanner.cmake
@@ -0,0 +1,212 @@
+# SPDX-FileCopyrightText: 2012-2014 Pier Luigi Fiorini
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindQtWaylandScanner
+--------------------
+
+Try to find qtwaylandscanner.
+
+If the qtwaylandscanner executable is not in your PATH, you can provide
+an alternative name or full path location with the ``QtWaylandScanner_EXECUTABLE``
+variable.
+
+This will define the following variables:
+
+``QtWaylandScanner_FOUND``
+ True if qtwaylandscanner is available
+
+``QtWaylandScanner_EXECUTABLE``
+ The qtwaylandscanner executable.
+
+If ``QtWaylandScanner_FOUND`` is TRUE, it will also define the following imported
+target:
+
+``Wayland::QtScanner``
+ The qtwaylandscanner executable.
+
+This module provides the following functions to generate C++ protocol
+implementations:
+
+ - ``ecm_add_qtwayland_client_protocol``
+ - ``ecm_add_qtwayland_server_protocol``
+
+::
+
+ ecm_add_qtwayland_client_protocol(
+ PROTOCOL
+ BASENAME
+ [PREFIX ]
+ [PRIVATE_CODE])
+
+ ecm_add_qtwayland_client_protocol(
+ PROTOCOL
+ BASENAME
+ [PREFIX ]
+ [PRIVATE_CODE])
+
+Generate C++ wrapper to Wayland client protocol files from ````
+XML definition for the ```` interface and append those files
+to ```` or ````. Pass the ```` argument if the interface
+names don't start with ``qt_`` or ``wl_``.
+``PRIVATE_CODE`` instructs wayland-scanner to hide marshalling code
+from the compiled DSO for use in other DSOs. The default is to
+export this code.
+
+WaylandScanner is required and will be searched for.
+
+::
+
+ ecm_add_qtwayland_server_protocol(
+ PROTOCOL
+ BASENAME
+ [PREFIX ]
+ [PRIVATE_CODE])
+
+ ecm_add_qtwayland_server_protocol(
+ PROTOCOL
+ BASENAME
+ [PREFIX ]
+ [PRIVATE_CODE])
+
+Generate C++ wrapper to Wayland server protocol files from ````
+XML definition for the ```` interface and append those files
+to ```` or ````. Pass the ```` argument if the interface
+names don't start with ``qt_`` or ``wl_``.
+``PRIVATE_CODE`` instructs wayland-scanner to hide marshalling code
+from the compiled DSO for use in other DSOs. The default is to
+export this code.
+
+WaylandScanner is required and will be searched for.
+
+Since 1.4.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+include("${ECM_MODULE_DIR}/ECMQueryQt.cmake")
+
+ecm_find_package_version_check(QtWaylandScanner)
+
+if (QT_MAJOR_VERSION STREQUAL "5")
+ ecm_query_qt(qtwaylandscanner_dir QT_HOST_BINS)
+else()
+ ecm_query_qt(qtwaylandscanner_dir QT_HOST_LIBEXECS)
+endif()
+
+# Find qtwaylandscanner
+find_program(QtWaylandScanner_EXECUTABLE NAMES qtwaylandscanner HINTS ${qtwaylandscanner_dir})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(QtWaylandScanner
+ FOUND_VAR
+ QtWaylandScanner_FOUND
+ REQUIRED_VARS
+ QtWaylandScanner_EXECUTABLE
+)
+
+mark_as_advanced(QtWaylandScanner_EXECUTABLE)
+
+if(NOT TARGET Wayland::QtScanner AND QtWaylandScanner_FOUND)
+ add_executable(Wayland::QtScanner IMPORTED)
+ set_target_properties(Wayland::QtScanner PROPERTIES
+ IMPORTED_LOCATION "${QtWaylandScanner_EXECUTABLE}"
+ )
+endif()
+
+include(FeatureSummary)
+set_package_properties(QtWaylandScanner PROPERTIES
+ URL "https://qt.io/"
+ DESCRIPTION "Executable that converts XML protocol files to C++ code"
+)
+
+function(ecm_add_qtwayland_client_protocol target_or_sources_var)
+ # Parse arguments
+ set(oneValueArgs PROTOCOL BASENAME PREFIX)
+ set(options PRIVATE_CODE)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to ecm_add_qtwayland_client_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ set(_prefix "${ARGS_PREFIX}")
+ if(ARGS_PRIVATE_CODE)
+ set(_private_code_option PRIVATE_CODE)
+ endif()
+
+ find_package(WaylandScanner REQUIRED QUIET)
+ ecm_add_wayland_client_protocol(${target_or_sources_var}
+ PROTOCOL ${ARGS_PROTOCOL}
+ BASENAME ${ARGS_BASENAME}
+ ${_private_code_option})
+
+ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
+ set(_header "${CMAKE_CURRENT_BINARY_DIR}/qwayland-${ARGS_BASENAME}.h")
+ set(_code "${CMAKE_CURRENT_BINARY_DIR}/qwayland-${ARGS_BASENAME}.cpp")
+
+ set_source_files_properties(${_header} ${_code} GENERATED)
+
+ add_custom_command(OUTPUT "${_header}"
+ COMMAND ${QtWaylandScanner_EXECUTABLE} client-header ${_infile} "" ${_prefix} > ${_header}
+ DEPENDS ${_infile} ${_cheader} VERBATIM)
+
+ add_custom_command(OUTPUT "${_code}"
+ COMMAND ${QtWaylandScanner_EXECUTABLE} client-code ${_infile} "" ${_prefix} > ${_code}
+ DEPENDS ${_infile} ${_header} VERBATIM)
+
+ set_property(SOURCE ${_header} ${_code} PROPERTY SKIP_AUTOMOC ON)
+
+ if (TARGET ${target_or_sources_var})
+ target_sources(${target_or_sources_var} PRIVATE "${_code}")
+ else()
+ list(APPEND ${target_or_sources_var} "${_code}")
+ set(${target_or_sources_var} ${${target_or_sources_var}} PARENT_SCOPE)
+ endif()
+endfunction()
+
+
+function(ecm_add_qtwayland_server_protocol target_or_sources_var)
+ # Parse arguments
+ set(oneValueArgs PROTOCOL BASENAME PREFIX)
+ set(options PRIVATE_CODE)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to ecm_add_qtwayland_server_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ set(_prefix "${ARGS_PREFIX}")
+ if(ARGS_PRIVATE_CODE)
+ set(_private_code_option PRIVATE_CODE)
+ endif()
+
+ find_package(WaylandScanner REQUIRED QUIET)
+ ecm_add_wayland_server_protocol(${target_or_sources_var}
+ PROTOCOL ${ARGS_PROTOCOL}
+ BASENAME ${ARGS_BASENAME}
+ ${_private_code_option})
+
+ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
+ set(_header "${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-${ARGS_BASENAME}.h")
+ set(_code "${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-${ARGS_BASENAME}.cpp")
+
+ set_source_files_properties(${_header} ${_code} GENERATED)
+
+ add_custom_command(OUTPUT "${_header}"
+ COMMAND ${QtWaylandScanner_EXECUTABLE} server-header ${_infile} "" ${_prefix} > ${_header}
+ DEPENDS ${_infile} VERBATIM)
+
+ add_custom_command(OUTPUT "${_code}"
+ COMMAND ${QtWaylandScanner_EXECUTABLE} server-code ${_infile} "" ${_prefix} > ${_code}
+ DEPENDS ${_infile} ${_header} VERBATIM)
+
+ set_property(SOURCE ${_header} ${_code} PROPERTY SKIP_AUTOMOC ON)
+
+ if (TARGET ${target_or_sources_var})
+ target_sources(${target_or_sources_var} PRIVATE "${_code}")
+ else()
+ list(APPEND ${target_or_sources_var} "${_code}")
+ set(${target_or_sources_var} ${${target_or_sources_var}} PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/cmake/FindSDL2.cmake b/cmake/find-modules/FindSDL2.cmake
similarity index 100%
rename from cmake/FindSDL2.cmake
rename to cmake/find-modules/FindSDL2.cmake
diff --git a/cmake/find-modules/FindUDev.cmake b/cmake/find-modules/FindUDev.cmake
new file mode 100644
index 000000000000..bab092f8a03f
--- /dev/null
+++ b/cmake/find-modules/FindUDev.cmake
@@ -0,0 +1,71 @@
+# SPDX-FileCopyrightText: 2010 Rafael Fernández López
+# SPDX-FileCopyrightText: 2019 Volker Krause
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindUDev
+--------
+
+Try to find the UDev library.
+
+This will define the following variables:
+
+``UDev_FOUND``
+ System has UDev.
+
+``UDev_INCLUDE_DIRS``
+ The libudev include directory.
+
+``UDev_LIBRARIES``
+ The libudev libraries.
+
+``UDev_VERSION``
+ The libudev version.
+
+If ``UDev_FOUND`` is TRUE, it will also define the following imported
+target:
+
+``UDev::UDev``
+ The UDev library
+
+Since 5.57.0.
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_UDEV QUIET libudev)
+
+find_path(UDev_INCLUDE_DIRS NAMES libudev.h HINTS ${PC_UDEV_INCLUDE_DIRS})
+find_library(UDev_LIBRARIES NAMES udev HINTS ${PC_UDEV_LIBRARY_DIRS})
+
+set(UDev_VERSION ${PC_UDEV_VERSION})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(UDev
+ FOUND_VAR UDev_FOUND
+ REQUIRED_VARS UDev_INCLUDE_DIRS UDev_LIBRARIES
+ VERSION_VAR UDev_VERSION
+)
+
+mark_as_advanced(UDev_INCLUDE_DIRS UDev_LIBRARIES)
+
+if(UDev_FOUND AND NOT TARGET UDev::UDev)
+ add_library(UDev::UDev UNKNOWN IMPORTED)
+ set_target_properties(UDev::UDev PROPERTIES
+ IMPORTED_LOCATION "${UDev_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${UDev_INCLUDE_DIRS}"
+ INTERFACE_COMPILE_DEFINITIONS "${PC_UDEV_CFLAGS_OTHER}"
+ )
+endif()
+
+# backward compat variables, remove for KF6
+set(UDEV_FOUND ${UDev_FOUND})
+set(UDEV_LIBS ${UDev_LIBRARIES})
+set(UDEV_INCLUDE_DIR ${UDev_INCLUDE_DIRS})
+mark_as_advanced(UDEV_FOUND UDEV_LIBS UDEV_INCLUDE_DIR)
+
+include(FeatureSummary)
+set_package_properties(UDev PROPERTIES
+ DESCRIPTION "API for enumerating and introspecting local devices (part of systemd)"
+ URL "https://www.freedesktop.org/wiki/Software/systemd/"
+)
diff --git a/cmake/find-modules/FindWayland.cmake b/cmake/find-modules/FindWayland.cmake
new file mode 100644
index 000000000000..926fd4855282
--- /dev/null
+++ b/cmake/find-modules/FindWayland.cmake
@@ -0,0 +1,137 @@
+# SPDX-FileCopyrightText: 2014 Alex Merry
+# SPDX-FileCopyrightText: 2014 Martin Gräßlin
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindWayland
+-----------
+
+Try to find Wayland.
+
+This is a component-based find module, which makes use of the COMPONENTS
+and OPTIONAL_COMPONENTS arguments to find_module. The following components
+are available::
+
+ Client Server Cursor Egl
+
+If no components are specified, this module will act as though all components
+were passed to OPTIONAL_COMPONENTS.
+
+This module will define the following variables, independently of the
+components searched for or found:
+
+``Wayland_FOUND``
+ TRUE if (the requested version of) Wayland is available
+``Wayland_VERSION``
+ Found Wayland version
+``Wayland_TARGETS``
+ A list of all targets imported by this module (note that there may be more
+ than the components that were requested)
+``Wayland_LIBRARIES``
+ This can be passed to target_link_libraries() instead of the imported
+ targets
+``Wayland_INCLUDE_DIRS``
+ This should be passed to target_include_directories() if the targets are
+ not used for linking
+``Wayland_DEFINITIONS``
+ This should be passed to target_compile_options() if the targets are not
+ used for linking
+``Wayland_DATADIR``
+ The core wayland protocols data directory
+ Since 5.73.0
+
+For each searched-for components, ``Wayland__FOUND`` will be set to
+TRUE if the corresponding Wayland library was found, and FALSE otherwise. If
+``Wayland__FOUND`` is TRUE, the imported target
+``Wayland::`` will be defined. This module will also attempt to
+determine ``Wayland_*_VERSION`` variables for each imported target, although
+``Wayland_VERSION`` should normally be sufficient.
+
+In general we recommend using the imported targets, as they are easier to use
+and provide more control. Bear in mind, however, that if any target is in the
+link interface of an exported library, it must be made available by the
+package config file.
+
+Since pre-1.0.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+
+ecm_find_package_version_check(Wayland)
+
+set(Wayland_known_components
+ Client
+ Server
+ Cursor
+ Egl
+)
+foreach(_comp ${Wayland_known_components})
+ string(TOLOWER "${_comp}" _lc_comp)
+ set(Wayland_${_comp}_component_deps)
+ set(Wayland_${_comp}_pkg_config "wayland-${_lc_comp}")
+ set(Wayland_${_comp}_lib "wayland-${_lc_comp}")
+ set(Wayland_${_comp}_header "wayland-${_lc_comp}.h")
+endforeach()
+set(Wayland_Egl_component_deps Client)
+
+ecm_find_package_parse_components(Wayland
+ RESULT_VAR Wayland_components
+ KNOWN_COMPONENTS ${Wayland_known_components}
+)
+ecm_find_package_handle_library_components(Wayland
+ COMPONENTS ${Wayland_components}
+)
+
+# If pkg-config didn't provide us with version information,
+# try to extract it from wayland-version.h
+# (Note that the version from wayland-egl.pc will probably be
+# the Mesa version, rather than the Wayland version, but that
+# version will be ignored as we always find wayland-client.pc
+# first).
+if(NOT Wayland_VERSION)
+ find_file(Wayland_VERSION_HEADER
+ NAMES wayland-version.h
+ HINTS ${Wayland_INCLUDE_DIRS}
+ )
+ mark_as_advanced(Wayland_VERSION_HEADER)
+ if(Wayland_VERSION_HEADER)
+ file(READ ${Wayland_VERSION_HEADER} _wayland_version_header_contents)
+ string(REGEX REPLACE
+ "^.*[ \t]+WAYLAND_VERSION[ \t]+\"([0-9.]*)\".*$"
+ "\\1"
+ Wayland_VERSION
+ "${_wayland_version_header_contents}"
+ )
+ unset(_wayland_version_header_contents)
+ endif()
+endif()
+
+find_package_handle_standard_args(Wayland
+ FOUND_VAR
+ Wayland_FOUND
+ REQUIRED_VARS
+ Wayland_LIBRARIES
+ VERSION_VAR
+ Wayland_VERSION
+ HANDLE_COMPONENTS
+)
+
+pkg_get_variable(Wayland_DATADIR wayland-scanner pkgdatadir)
+if (CMAKE_CROSSCOMPILING AND (NOT EXISTS "${Wayland_DATADIR}/wayland.xml"))
+ # PKG_CONFIG_SYSROOT_DIR only applies to -I and -L flags, so pkg-config
+ # does not prepend CMAKE_SYSROOT when cross-compiling unless you pass
+ # --define-prefix explicitly. Therefore we have to manually do prepend
+ # it here when cross-compiling.
+ # See https://gitlab.kitware.com/cmake/cmake/-/issues/16647#note_844761
+ set(Wayland_DATADIR ${CMAKE_SYSROOT}${Wayland_DATADIR})
+endif()
+if (NOT EXISTS "${Wayland_DATADIR}/wayland.xml")
+ message(WARNING "Could not find wayland.xml in ${Wayland_DATADIR}")
+endif()
+
+include(FeatureSummary)
+set_package_properties(Wayland PROPERTIES
+ URL "https://wayland.freedesktop.org/"
+ DESCRIPTION "C library implementation of the Wayland protocol: a protocol for a compositor to talk to its clients"
+)
diff --git a/cmake/find-modules/FindWaylandProtocols.cmake b/cmake/find-modules/FindWaylandProtocols.cmake
new file mode 100644
index 000000000000..a4449885d99f
--- /dev/null
+++ b/cmake/find-modules/FindWaylandProtocols.cmake
@@ -0,0 +1,38 @@
+# SPDX-FileCopyrightText: 2019 Vlad Zahorodnii
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindWaylandProtocols
+--------------------
+
+Try to find wayland-protocols on a Unix system.
+
+This will define the following variables:
+
+``WaylandProtocols_FOUND``
+ True if (the requested version of) wayland-protocols is available
+``WaylandProtocols_VERSION``
+ The version of wayland-protocols
+``WaylandProtocols_DATADIR``
+ The wayland protocols data directory
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PKG_wayland_protocols QUIET wayland-protocols)
+
+set(WaylandProtocols_VERSION ${PKG_wayland_protocols_VERSION})
+pkg_get_variable(WaylandProtocols_DATADIR wayland-protocols pkgdatadir)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(WaylandProtocols
+ FOUND_VAR WaylandProtocols_FOUND
+ REQUIRED_VARS WaylandProtocols_DATADIR
+ VERSION_VAR WaylandProtocols_VERSION
+)
+
+include(FeatureSummary)
+set_package_properties(WaylandProtocols PROPERTIES
+ DESCRIPTION "Specifications of extended Wayland protocols"
+ URL "https://wayland.freedesktop.org/"
+)
diff --git a/cmake/find-modules/FindWaylandScanner.cmake b/cmake/find-modules/FindWaylandScanner.cmake
new file mode 100644
index 000000000000..2fa1fd6e8bc2
--- /dev/null
+++ b/cmake/find-modules/FindWaylandScanner.cmake
@@ -0,0 +1,183 @@
+# SPDX-FileCopyrightText: 2012-2014 Pier Luigi Fiorini
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindWaylandScanner
+------------------
+
+Try to find wayland-scanner.
+
+If the wayland-scanner executable is not in your PATH, you can provide
+an alternative name or full path location with the ``WaylandScanner_EXECUTABLE``
+variable.
+
+This will define the following variables:
+
+``WaylandScanner_FOUND``
+ True if wayland-scanner is available.
+
+``WaylandScanner_EXECUTABLE``
+ The wayland-scanner executable.
+
+If ``WaylandScanner_FOUND`` is TRUE, it will also define the following imported
+target:
+
+``Wayland::Scanner``
+ The wayland-scanner executable.
+
+This module provides the following functions to generate C protocol
+implementations:
+
+ - ``ecm_add_wayland_client_protocol``
+ - ``ecm_add_wayland_server_protocol``
+
+::
+
+ ecm_add_wayland_client_protocol(
+ PROTOCOL
+ BASENAME
+ [PRIVATE_CODE])
+
+ ecm_add_wayland_client_protocol(
+ PROTOCOL
+ BASENAME
+ [PRIVATE_CODE])
+
+Generate Wayland client protocol files from ```` XML
+definition for the ```` interface and append those files
+to ```` or ````.
+
+``PRIVATE_CODE`` instructs wayland-scanner to hide marshalling code
+from the compiled DSO for use in other DSOs. The default is to
+export this code.
+
+::
+
+ ecm_add_wayland_server_protocol(
+ PROTOCOL
+ BASENAME
+ [PRIVATE_CODE])
+
+ ecm_add_wayland_server_protocol(
+ PROTOCOL
+ BASENAME
+ [PRIVATE_CODE])
+
+Generate Wayland server protocol files from ```` XML
+definition for the ```` interface and append those files
+to ```` or ````.
+
+``PRIVATE_CODE`` instructs wayland-scanner to hide marshalling code
+from the compiled DSO for use in other DSOs. The default is to
+export this code.
+
+Since 1.4.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+
+ecm_find_package_version_check(WaylandScanner)
+
+# Find wayland-scanner
+find_program(WaylandScanner_EXECUTABLE NAMES wayland-scanner)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(WaylandScanner
+ FOUND_VAR
+ WaylandScanner_FOUND
+ REQUIRED_VARS
+ WaylandScanner_EXECUTABLE
+)
+
+mark_as_advanced(WaylandScanner_EXECUTABLE)
+
+if(NOT TARGET Wayland::Scanner AND WaylandScanner_FOUND)
+ add_executable(Wayland::Scanner IMPORTED)
+ set_target_properties(Wayland::Scanner PROPERTIES
+ IMPORTED_LOCATION "${WaylandScanner_EXECUTABLE}"
+ )
+endif()
+
+include(FeatureSummary)
+set_package_properties(WaylandScanner PROPERTIES
+ URL "https://wayland.freedesktop.org/"
+ DESCRIPTION "Executable that converts XML protocol files to C code"
+)
+
+function(ecm_add_wayland_client_protocol target_or_sources_var)
+ # Parse arguments
+ set(options PRIVATE_CODE)
+ set(oneValueArgs PROTOCOL BASENAME)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_client_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
+ set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.h")
+ set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c")
+ if(ARGS_PRIVATE_CODE)
+ set(_code_type private-code)
+ else()
+ set(_code_type public-code)
+ endif()
+
+ set_source_files_properties(${_client_header} GENERATED)
+ set_source_files_properties(${_code} GENERATED)
+ set_property(SOURCE ${_client_header} ${_code} PROPERTY SKIP_AUTOMOC ON)
+
+ add_custom_command(OUTPUT "${_client_header}"
+ COMMAND ${WaylandScanner_EXECUTABLE} client-header ${_infile} ${_client_header}
+ DEPENDS ${_infile} VERBATIM)
+
+ add_custom_command(OUTPUT "${_code}"
+ COMMAND ${WaylandScanner_EXECUTABLE} ${_code_type} ${_infile} ${_code}
+ DEPENDS ${_infile} ${_client_header} VERBATIM)
+
+ if (TARGET ${target_or_sources_var})
+ target_sources(${target_or_sources_var} PRIVATE "${_client_header}" "${_code}")
+ else()
+ list(APPEND ${target_or_sources_var} "${_client_header}" "${_code}")
+ set(${target_or_sources_var} ${${target_or_sources_var}} PARENT_SCOPE)
+ endif()
+endfunction()
+
+
+function(ecm_add_wayland_server_protocol target_or_sources_var)
+ # Parse arguments
+ set(options PRIVATE_CODE)
+ set(oneValueArgs PROTOCOL BASENAME)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_server_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ if(ARGS_PRIVATE_CODE)
+ set(_private_code_option PRIVATE_CODE)
+ endif()
+
+ ecm_add_wayland_client_protocol(${target_or_sources_var}
+ PROTOCOL ${ARGS_PROTOCOL}
+ BASENAME ${ARGS_BASENAME}
+ ${_private_code_option})
+
+ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
+ set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-server-protocol.h")
+ set(_server_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c")
+ set_property(SOURCE ${_server_header} ${_server_code} PROPERTY SKIP_AUTOMOC ON)
+ set_source_files_properties(${_server_header} GENERATED)
+
+ add_custom_command(OUTPUT "${_server_header}"
+ COMMAND ${WaylandScanner_EXECUTABLE} server-header ${_infile} ${_server_header}
+ DEPENDS ${_infile} VERBATIM)
+
+ if (TARGET ${target_or_sources_var})
+ target_sources(${target_or_sources_var} PRIVATE "${_server_header}")
+ else()
+ list(APPEND ${target_or_sources_var} "${_server_header}")
+ set(${target_or_sources_var} ${${target_or_sources_var}} PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/cmake/find-modules/FindX11_XCB.cmake b/cmake/find-modules/FindX11_XCB.cmake
new file mode 100644
index 000000000000..f571bacff46e
--- /dev/null
+++ b/cmake/find-modules/FindX11_XCB.cmake
@@ -0,0 +1,96 @@
+# SPDX-FileCopyrightText: 2014 Alex Merry
+# SPDX-FileCopyrightText: 2011 Fredrik Höglund
+# SPDX-FileCopyrightText: 2008 Helio Chissini de Castro
+# SPDX-FileCopyrightText: 2007 Matthias Kretz
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindX11_XCB
+-----------
+
+Try to find the X11 XCB compatibility library.
+
+This will define the following variables:
+
+``X11_XCB_FOUND``
+ True if (the requested version of) libX11-xcb is available
+``X11_XCB_VERSION``
+ The version of libX11-xcb (this is not guaranteed to be set even when
+ X11_XCB_FOUND is true)
+``X11_XCB_LIBRARIES``
+ This can be passed to target_link_libraries() instead of the ``EGL::EGL``
+ target
+``X11_XCB_INCLUDE_DIR``
+ This should be passed to target_include_directories() if the target is not
+ used for linking
+``X11_XCB_DEFINITIONS``
+ This should be passed to target_compile_options() if the target is not
+ used for linking
+
+If ``X11_XCB_FOUND`` is TRUE, it will also define the following imported
+target:
+
+``X11::XCB``
+ The X11 XCB compatibility library
+
+In general we recommend using the imported target, as it is easier to use.
+Bear in mind, however, that if the target is in the link interface of an
+exported library, it must be made available by the package config file.
+
+Since pre-1.0.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+
+ecm_find_package_version_check(X11_XCB)
+
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+find_package(PkgConfig QUIET)
+pkg_check_modules(PKG_X11_XCB QUIET x11-xcb)
+
+set(X11_XCB_DEFINITIONS ${PKG_X11_XCB_CFLAGS_OTHER})
+set(X11_XCB_VERSION ${PKG_X11_XCB_VERSION})
+
+find_path(X11_XCB_INCLUDE_DIR
+ NAMES X11/Xlib-xcb.h
+ HINTS ${PKG_X11_XCB_INCLUDE_DIRS}
+)
+find_library(X11_XCB_LIBRARY
+ NAMES X11-xcb
+ HINTS ${PKG_X11_XCB_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(X11_XCB
+ FOUND_VAR
+ X11_XCB_FOUND
+ REQUIRED_VARS
+ X11_XCB_LIBRARY
+ X11_XCB_INCLUDE_DIR
+ VERSION_VAR
+ X11_XCB_VERSION
+)
+
+if(X11_XCB_FOUND AND NOT TARGET X11::XCB)
+ add_library(X11::XCB UNKNOWN IMPORTED)
+ set_target_properties(X11::XCB PROPERTIES
+ IMPORTED_LOCATION "${X11_XCB_LIBRARY}"
+ INTERFACE_COMPILE_OPTIONS "${X11_XCB_DEFINITIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${X11_XCB_INCLUDE_DIR}"
+ )
+endif()
+
+mark_as_advanced(X11_XCB_INCLUDE_DIR X11_XCB_LIBRARY)
+
+# compatibility variables
+set(X11_XCB_LIBRARIES ${X11_XCB_LIBRARY})
+set(X11_XCB_INCLUDE_DIRS ${X11_XCB_INCLUDE_DIR})
+set(X11_XCB_VERSION_STRING ${X11_XCB_VERSION})
+
+include(FeatureSummary)
+set_package_properties(X11_XCB PROPERTIES
+ URL "https://xorg.freedesktop.org/"
+ DESCRIPTION "A compatibility library for code that translates Xlib API calls into XCB calls"
+)
diff --git a/cmake/find-modules/FindXCB.cmake b/cmake/find-modules/FindXCB.cmake
new file mode 100644
index 000000000000..f18c2fd09595
--- /dev/null
+++ b/cmake/find-modules/FindXCB.cmake
@@ -0,0 +1,168 @@
+# SPDX-FileCopyrightText: 2011 Fredrik Höglund
+# SPDX-FileCopyrightText: 2013 Martin Gräßlin
+# SPDX-FileCopyrightText: 2014-2015 Alex Merry
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+FindXCB
+-------
+
+Try to find XCB.
+
+This is a component-based find module, which makes use of the COMPONENTS and
+OPTIONAL_COMPONENTS arguments to find_module. The following components are
+available::
+
+ XCB
+ ATOM AUX COMPOSITE CURSOR DAMAGE
+ DPMS DRI2 DRI3 EVENT EWMH
+ GLX ICCCM IMAGE KEYSYMS PRESENT
+ RANDR RECORD RENDER RENDERUTIL RES
+ SCREENSAVER SHAPE SHM SYNC UTIL
+ XF86DRI XFIXES XINERAMA XINPUT XKB
+ XTEST XV XVMC
+
+If no components are specified, this module will act as though all components
+were passed to OPTIONAL_COMPONENTS. Before 5.82 this excluded XINPUT. Since 5.82
+all components are searched for.
+
+This module will define the following variables, independently of the
+components searched for or found:
+
+``XCB_FOUND``
+ True if (the requestion version of) xcb is available
+``XCB_VERSION``
+ Found xcb version
+``XCB_TARGETS``
+ A list of all targets imported by this module (note that there may be more
+ than the components that were requested)
+``XCB_LIBRARIES``
+ This can be passed to target_link_libraries() instead of the imported
+ targets
+``XCB_INCLUDE_DIRS``
+ This should be passed to target_include_directories() if the targets are
+ not used for linking
+``XCB_DEFINITIONS``
+ This should be passed to target_compile_options() if the targets are not
+ used for linking
+
+For each searched-for components, ``XCB__FOUND`` will be set to
+true if the corresponding xcb library was found, and false otherwise. If
+``XCB__FOUND`` is true, the imported target ``XCB::``
+will be defined. This module will also attempt to determine
+``XCB_*_VERSION`` variables for each imported target, although
+``XCB_VERSION`` should normally be sufficient.
+
+In general we recommend using the imported targets, as they are easier to use
+and provide more control. Bear in mind, however, that if any target is in the
+link interface of an exported library, it must be made available by the
+package config file.
+
+Since pre-1.0.0.
+#]=======================================================================]
+
+include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpersStub.cmake)
+
+ecm_find_package_version_check(XCB)
+
+# Note that this list needs to be ordered such that any component
+# appears after its dependencies
+set(XCB_known_components
+ XCB
+ RENDER
+ SHAPE
+ XFIXES
+ SHM
+ ATOM
+ AUX
+ COMPOSITE
+ CURSOR
+ DAMAGE
+ DPMS
+ DRI2
+ DRI3
+ EVENT
+ EWMH
+ GLX
+ ICCCM
+ IMAGE
+ KEYSYMS
+ PRESENT
+ RANDR
+ RECORD
+ RENDERUTIL
+ RES
+ SCREENSAVER
+ SYNC
+ UTIL
+ XF86DRI
+ XINERAMA
+ XINPUT
+ XKB
+ XTEST
+ XV
+ XVMC
+)
+
+# default component info: xcb components have fairly predictable
+# header files, library names and pkg-config names
+foreach(_comp ${XCB_known_components})
+ string(TOLOWER "${_comp}" _lc_comp)
+ set(XCB_${_comp}_component_deps XCB)
+ set(XCB_${_comp}_pkg_config "xcb-${_lc_comp}")
+ set(XCB_${_comp}_lib "xcb-${_lc_comp}")
+ set(XCB_${_comp}_header "xcb/${_lc_comp}.h")
+endforeach()
+# exceptions
+set(XCB_XCB_component_deps)
+set(XCB_COMPOSITE_component_deps XCB XFIXES)
+set(XCB_DAMAGE_component_deps XCB XFIXES)
+set(XCB_IMAGE_component_deps XCB SHM)
+set(XCB_RENDERUTIL_component_deps XCB RENDER)
+set(XCB_XFIXES_component_deps XCB RENDER SHAPE)
+set(XCB_XVMC_component_deps XCB XV)
+set(XCB_XV_component_deps XCB SHM)
+set(XCB_XCB_pkg_config "xcb")
+set(XCB_XCB_lib "xcb")
+set(XCB_ATOM_header "xcb/xcb_atom.h")
+set(XCB_ATOM_lib "xcb-util")
+set(XCB_AUX_header "xcb/xcb_aux.h")
+set(XCB_AUX_lib "xcb-util")
+set(XCB_CURSOR_header "xcb/xcb_cursor.h")
+set(XCB_EVENT_header "xcb/xcb_event.h")
+set(XCB_EVENT_lib "xcb-util")
+set(XCB_EWMH_header "xcb/xcb_ewmh.h")
+set(XCB_ICCCM_header "xcb/xcb_icccm.h")
+set(XCB_IMAGE_header "xcb/xcb_image.h")
+set(XCB_KEYSYMS_header "xcb/xcb_keysyms.h")
+set(XCB_PIXEL_header "xcb/xcb_pixel.h")
+set(XCB_RENDERUTIL_header "xcb/xcb_renderutil.h")
+set(XCB_RENDERUTIL_lib "xcb-render-util")
+set(XCB_UTIL_header "xcb/xcb_util.h")
+
+ecm_find_package_parse_components(XCB
+ RESULT_VAR XCB_components
+ KNOWN_COMPONENTS ${XCB_known_components}
+ DEFAULT_COMPONENTS ${XCB_default_components}
+)
+
+ecm_find_package_handle_library_components(XCB
+ COMPONENTS ${XCB_components}
+)
+
+find_package_handle_standard_args(XCB
+ FOUND_VAR
+ XCB_FOUND
+ REQUIRED_VARS
+ XCB_LIBRARIES
+ VERSION_VAR
+ XCB_VERSION
+ HANDLE_COMPONENTS
+)
+
+include(FeatureSummary)
+set_package_properties(XCB PROPERTIES
+ URL "https://xcb.freedesktop.org/"
+ DESCRIPTION "X protocol C-language Binding"
+)
diff --git a/cmake/modules/ECMFindModuleHelpers.cmake b/cmake/modules/ECMFindModuleHelpers.cmake
new file mode 100644
index 000000000000..92c796e6bdd5
--- /dev/null
+++ b/cmake/modules/ECMFindModuleHelpers.cmake
@@ -0,0 +1,277 @@
+# SPDX-FileCopyrightText: 2014 Alex Merry
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+#[=======================================================================[.rst:
+ECMFindModuleHelpers
+--------------------
+
+Helper macros for find modules: ``ecm_find_package_version_check()``,
+``ecm_find_package_parse_components()`` and
+``ecm_find_package_handle_library_components()``.
+
+::
+
+ ecm_find_package_version_check()
+
+Prints warnings if the CMake version or the project's required CMake version
+is older than that required by extra-cmake-modules.
+
+::
+
+ ecm_find_package_parse_components(
+ RESULT_VAR
+ KNOWN_COMPONENTS [ [...]]
+ [SKIP_DEPENDENCY_HANDLING])
+
+This macro will populate with a list of components found in
+_FIND_COMPONENTS, after checking that all those components are in the
+list of ``KNOWN_COMPONENTS``; if there are any unknown components, it will print
+an error or warning (depending on the value of _FIND_REQUIRED) and call
+``return()``.
+
+The order of components in is guaranteed to match the order they
+are listed in the ``KNOWN_COMPONENTS`` argument.
+
+If ``SKIP_DEPENDENCY_HANDLING`` is not set, for each component the variable
+__component_deps will be checked for dependent components.
+If is listed in _FIND_COMPONENTS, then all its (transitive)
+dependencies will also be added to .
+
+::
+
+ ecm_find_package_handle_library_components(
+ COMPONENTS [ [...]]
+ [SKIP_DEPENDENCY_HANDLING])
+ [SKIP_PKG_CONFIG])
+
+Creates an imported library target for each component. The operation of this
+macro depends on the presence of a number of CMake variables.
+
+The __lib variable should contain the name of this library,
+and __header variable should contain the name of a header
+file associated with it (whatever relative path is normally passed to
+'#include'). __header_subdir variable can be used to specify
+which subdirectory of the include path the headers will be found in.
+``ecm_find_package_components()`` will then search for the library
+and include directory (creating appropriate cache variables) and create an
+imported library target named ::.
+
+Additional variables can be used to provide additional information:
+
+If ``SKIP_PKG_CONFIG``, the __pkg_config variable is set, and
+pkg-config is found, the pkg-config module given by
+__pkg_config will be searched for and used to help locate the
+library and header file. It will also be used to set
+__VERSION.
+
+Note that if version information is found via pkg-config,
+__FIND_VERSION can be set to require a particular version
+for each component.
+
+If ``SKIP_DEPENDENCY_HANDLING`` is not set, the ``INTERFACE_LINK_LIBRARIES`` property
+of the imported target for will be set to contain the imported
+targets for the components listed in __component_deps.
+_FOUND will also be set to ``FALSE`` if any of the components in
+__component_deps are not found. This requires the components
+in __component_deps to be listed before in the
+``COMPONENTS`` argument.
+
+The following variables will be set:
+
+``_TARGETS``
+ the imported targets
+``_LIBRARIES``
+ the found libraries
+``_INCLUDE_DIRS``
+ the combined required include directories for the components
+``_DEFINITIONS``
+ the "other" CFLAGS provided by pkg-config, if any
+``_VERSION``
+ the value of ``__VERSION`` for the first component that
+ has this variable set (note that components are searched for in the order
+ they are passed to the macro), although if it is already set, it will not
+ be altered
+
+.. note::
+ These variables are never cleared, so if
+ ``ecm_find_package_handle_library_components()`` is called multiple times with
+ different components (typically because of multiple ``find_package()`` calls) then
+ ``_TARGETS``, for example, will contain all the targets found in any
+ call (although no duplicates).
+
+Since pre-1.0.0.
+#]=======================================================================]
+
+macro(ecm_find_package_version_check module_name)
+ if(CMAKE_VERSION VERSION_LESS 3.16.0)
+ message(FATAL_ERROR "CMake 3.16.0 is required by Find${module_name}.cmake")
+ endif()
+ if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.16.0)
+ message(AUTHOR_WARNING "Your project should require at least CMake 3.16.0 to use Find${module_name}.cmake")
+ endif()
+endmacro()
+
+macro(ecm_find_package_parse_components module_name)
+ set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)
+ set(ecm_fppc_oneValueArgs RESULT_VAR)
+ set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)
+ cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})
+
+ if(ECM_FPPC_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")
+ endif()
+ if(NOT ECM_FPPC_RESULT_VAR)
+ message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")
+ endif()
+ if(NOT ECM_FPPC_KNOWN_COMPONENTS)
+ message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")
+ endif()
+ if(NOT ECM_FPPC_DEFAULT_COMPONENTS)
+ set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})
+ endif()
+
+ if(${module_name}_FIND_COMPONENTS)
+ set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})
+
+ if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)
+ # Make sure deps are included
+ foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})
+ foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})
+ list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)
+ if("${ecm_fppc_index}" STREQUAL "-1")
+ if(NOT ${module_name}_FIND_QUIETLY)
+ message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")
+ endif()
+ list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")
+ endif()
+ endforeach()
+ endforeach()
+ else()
+ message(STATUS "Skipping dependency handling for ${module_name}")
+ endif()
+ list(REMOVE_DUPLICATES ecm_fppc_requestedComps)
+
+ # This makes sure components are listed in the same order as
+ # KNOWN_COMPONENTS (potentially important for inter-dependencies)
+ set(${ECM_FPPC_RESULT_VAR})
+ foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})
+ list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)
+ if(NOT "${ecm_fppc_index}" STREQUAL "-1")
+ list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")
+ list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})
+ endif()
+ endforeach()
+ # if there are any left, they are unknown components
+ if(ecm_fppc_requestedComps)
+ set(ecm_fppc_msgType STATUS)
+ if(${module_name}_FIND_REQUIRED)
+ set(ecm_fppc_msgType FATAL_ERROR)
+ endif()
+ if(NOT ${module_name}_FIND_QUIETLY)
+ message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")
+ endif()
+ return()
+ endif()
+ else()
+ set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})
+ endif()
+endmacro()
+
+macro(ecm_find_package_handle_library_components module_name)
+ set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)
+ set(ecm_fpwc_oneValueArgs)
+ set(ecm_fpwc_multiValueArgs COMPONENTS)
+ cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})
+
+ if(ECM_FPWC_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")
+ endif()
+ if(NOT ECM_FPWC_COMPONENTS)
+ message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")
+ endif()
+
+ include(FindPackageHandleStandardArgs)
+ find_package(PkgConfig QUIET)
+ foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})
+ set(ecm_fpwc_dep_vars)
+ set(ecm_fpwc_dep_targets)
+ if(NOT SKIP_DEPENDENCY_HANDLING)
+ foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})
+ list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")
+ list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")
+ endforeach()
+ endif()
+
+ if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)
+ pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET
+ ${${module_name}_${ecm_fpwc_comp}_pkg_config})
+ endif()
+
+ find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
+ NAMES ${${module_name}_${ecm_fpwc_comp}_header}
+ HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}
+ PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}
+ )
+ find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY
+ NAMES ${${module_name}_${ecm_fpwc_comp}_lib}
+ HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}
+ )
+
+ set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")
+ if(NOT ${module_name}_VERSION)
+ set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})
+ endif()
+
+ set(FPHSA_NAME_MISMATCHED 1)
+ find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}
+ FOUND_VAR
+ ${module_name}_${ecm_fpwc_comp}_FOUND
+ REQUIRED_VARS
+ ${module_name}_${ecm_fpwc_comp}_LIBRARY
+ ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
+ ${ecm_fpwc_dep_vars}
+ VERSION_VAR
+ ${module_name}_${ecm_fpwc_comp}_VERSION
+ )
+ unset(FPHSA_NAME_MISMATCHED)
+
+ mark_as_advanced(
+ ${module_name}_${ecm_fpwc_comp}_LIBRARY
+ ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
+ )
+
+ if(${module_name}_${ecm_fpwc_comp}_FOUND)
+ list(APPEND ${module_name}_LIBRARIES
+ "${${module_name}_${ecm_fpwc_comp}_LIBRARY}")
+ list(APPEND ${module_name}_INCLUDE_DIRS
+ "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")
+ set(${module_name}_DEFINITIONS
+ ${${module_name}_DEFINITIONS}
+ ${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})
+ if(NOT TARGET ${module_name}::${ecm_fpwc_comp})
+ add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)
+ set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES
+ IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"
+ INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"
+ INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"
+ )
+ endif()
+ list(APPEND ${module_name}_TARGETS
+ "${module_name}::${ecm_fpwc_comp}")
+ endif()
+ endforeach()
+ if(${module_name}_LIBRARIES)
+ list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)
+ endif()
+ if(${module_name}_INCLUDE_DIRS)
+ list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)
+ endif()
+ if(${module_name}_DEFINITIONS)
+ list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)
+ endif()
+ if(${module_name}_TARGETS)
+ list(REMOVE_DUPLICATES ${module_name}_TARGETS)
+ endif()
+endmacro()
diff --git a/src/AnalyzeView/CMakeLists.txt b/src/AnalyzeView/CMakeLists.txt
index 4531ad9295b8..779077f2804a 100644
--- a/src/AnalyzeView/CMakeLists.txt
+++ b/src/AnalyzeView/CMakeLists.txt
@@ -58,10 +58,12 @@ target_link_libraries(AnalyzeView
set(MINIMUM_EXIV2_VERSION 0.28.3)
if(NOT QGC_BUILD_DEPENDENCIES)
- find_package(Exiv2 ${MINIMUM_EXIV2_VERSION} CONFIG)
- if(Exiv2_FOUND)
- message(STATUS "Found Exiv2 ${Exiv2_VERSION_STRING}")
- target_link_libraries(AnalyzeView PRIVATE Exiv2::exiv2lib)
+ find_package(Iconv)
+ find_package(EXPAT)
+ find_package(LibExiv2 ${MINIMUM_EXIV2_VERSION})
+ if(LibExiv2_FOUND)
+ message(STATUS "Found Exiv2 ${LibExiv2_VERSION}")
+ target_link_libraries(AnalyzeView PRIVATE LibExiv2::LibExiv2)
else()
find_package(PkgConfig)
if(PkgConfig_FOUND)
@@ -74,7 +76,7 @@ if(NOT QGC_BUILD_DEPENDENCIES)
endif()
endif()
-if(NOT Exiv2_FOUND)
+if(NOT Exiv2_FOUND AND NOT LibExiv2_FOUND)
message(STATUS "Building Exiv2")
include(FetchContent)
FetchContent_Declare(EXIV2
@@ -88,7 +90,7 @@ if(NOT Exiv2_FOUND)
set(EXIV2_ENABLE_PNG OFF CACHE INTERNAL "" FORCE)
set(EXIV2_ENABLE_NLS OFF CACHE INTERNAL "" FORCE)
set(EXIV2_ENABLE_LENSDATA OFF CACHE INTERNAL "" FORCE)
- set(EXIV2_ENABLE_DYNAMIC_RUNTIME ON CACHE INTERNAL "" FORCE)
+ set(EXIV2_ENABLE_DYNAMIC_RUNTIME OFF CACHE INTERNAL "" FORCE)
set(EXIV2_ENABLE_WEBREADY OFF CACHE INTERNAL "" FORCE)
set(EXIV2_ENABLE_CURL OFF CACHE INTERNAL "" FORCE)
set(EXIV2_ENABLE_BMFF OFF CACHE INTERNAL "" FORCE)
@@ -102,6 +104,7 @@ if(NOT Exiv2_FOUND)
set(EXIV2_BUILD_FUZZ_TESTS OFF CACHE INTERNAL "" FORCE)
set(EXIV2_BUILD_DOC OFF CACHE INTERNAL "" FORCE)
set(BUILD_WITH_CCACHE ON CACHE INTERNAL "" FORCE)
+ set(Iconv_FOUND OFF)
FetchContent_MakeAvailable(EXIV2)
target_link_libraries(AnalyzeView PRIVATE exiv2lib)
diff --git a/src/Settings/CMakeLists.txt b/src/Settings/CMakeLists.txt
index 9db4d8cf6688..3a9b440c2c24 100644
--- a/src/Settings/CMakeLists.txt
+++ b/src/Settings/CMakeLists.txt
@@ -51,6 +51,7 @@ target_link_libraries(Settings
PRIVATE
Qt6::Multimedia
API
+ GStreamerReceiver
QmlControls
Vehicle
VideoManager
diff --git a/src/Settings/VideoDecoderOptions.h b/src/Settings/VideoDecoderOptions.h
deleted file mode 100644
index f8ef9fec947b..000000000000
--- a/src/Settings/VideoDecoderOptions.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/****************************************************************************
-*
- * (c) 2009-2024 QGROUNDCONTROL PROJECT
- *
- * QGroundControl is licensed according to the terms in the file
- * COPYING.md in the root of the source code directory.
- *
- ****************************************************************************/
-
-#pragma once
-
-
-enum VideoDecoderOptions {
- ForceVideoDecoderDefault = 0,
- ForceVideoDecoderSoftware,
- ForceVideoDecoderNVIDIA,
- ForceVideoDecoderVAAPI,
- ForceVideoDecoderDirectX3D,
- ForceVideoDecoderVideoToolbox,
-};
diff --git a/src/Settings/VideoSettings.cc b/src/Settings/VideoSettings.cc
index 3b0b0df594aa..2d8931c60098 100644
--- a/src/Settings/VideoSettings.cc
+++ b/src/Settings/VideoSettings.cc
@@ -14,6 +14,10 @@
#include
#include
+#ifdef QGC_GST_STREAMING
+#include "GStreamer.h"
+#endif
+
#ifndef QGC_DISABLE_UVC
#include
#include
@@ -56,27 +60,29 @@ DECLARE_SETTINGGROUP(Video, "Video")
_nameToMetaDataMap[videoSourceName]->setEnumInfo(videoSourceCookedList, videoSourceList);
+#ifdef QGC_GST_STREAMING
const QVariantList removeForceVideoDecodeList{
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
- VideoDecoderOptions::ForceVideoDecoderDirectX3D,
- VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderDirectX3D,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
#elif defined(Q_OS_WIN)
- VideoDecoderOptions::ForceVideoDecoderVAAPI,
- VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVAAPI,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
#elif defined(Q_OS_MAC)
- VideoDecoderOptions::ForceVideoDecoderDirectX3D,
- VideoDecoderOptions::ForceVideoDecoderVAAPI,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderDirectX3D,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVAAPI,
#elif defined(Q_OS_ANDROID)
- VideoDecoderOptions::ForceVideoDecoderDirectX3D,
- VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
- VideoDecoderOptions::ForceVideoDecoderVAAPI,
- VideoDecoderOptions::ForceVideoDecoderNVIDIA,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderDirectX3D,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVideoToolbox,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderVAAPI,
+ GStreamer::VideoDecoderOptions::ForceVideoDecoderNVIDIA,
#endif
};
- for(const auto& value : removeForceVideoDecodeList) {
+ for (const auto &value : removeForceVideoDecodeList) {
_nameToMetaDataMap[forceVideoDecoderName]->removeEnumInfo(value);
}
+#endif
// Set default value for videoSource
_setDefaults();
diff --git a/src/Settings/VideoSettings.h b/src/Settings/VideoSettings.h
index daed65b6a6a5..51437f6cb867 100644
--- a/src/Settings/VideoSettings.h
+++ b/src/Settings/VideoSettings.h
@@ -10,7 +10,6 @@
#pragma once
#include "SettingsGroup.h"
-#include "VideoDecoderOptions.h"
class VideoSettings : public SettingsGroup
{
@@ -37,8 +36,6 @@ class VideoSettings : public SettingsGroup
DEFINE_SETTINGFACT(lowLatencyMode)
DEFINE_SETTINGFACT(forceVideoDecoder)
- Q_ENUM(VideoDecoderOptions)
-
Q_PROPERTY(bool streamConfigured READ streamConfigured NOTIFY streamConfiguredChanged)
Q_PROPERTY(QString rtspVideoSource READ rtspVideoSource CONSTANT)
Q_PROPERTY(QString udp264VideoSource READ udp264VideoSource CONSTANT)
diff --git a/src/VideoManager/VideoManager.cc b/src/VideoManager/VideoManager.cc
index ee2502322ec6..b3187332eed2 100644
--- a/src/VideoManager/VideoManager.cc
+++ b/src/VideoManager/VideoManager.cc
@@ -21,7 +21,6 @@
#include "SubtitleWriter.h"
#ifdef QGC_GST_STREAMING
#include "GStreamer.h"
-#include "VideoDecoderOptions.h"
#else
#include "GLVideoItemStub.h"
#endif
@@ -38,6 +37,7 @@
#include
#include
+#include
QGC_LOGGING_CATEGORY(VideoManagerLog, "qgc.videomanager.videomanager")
@@ -118,7 +118,7 @@ VideoManager::setToolbox(QGCToolbox *toolbox)
connect(pVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &VideoManager::_setActiveVehicle);
#ifdef QGC_GST_STREAMING
- GStreamer::blacklist(static_cast(_videoSettings->forceVideoDecoder()->rawValue().toInt()));
+ GStreamer::blacklist(static_cast(_videoSettings->forceVideoDecoder()->rawValue().toInt()));
#endif
int index = 0;
diff --git a/src/VideoManager/VideoReceiver/GStreamer/CMakeLists.txt b/src/VideoManager/VideoReceiver/GStreamer/CMakeLists.txt
index f1f723be9554..d77333d39936 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/CMakeLists.txt
+++ b/src/VideoManager/VideoReceiver/GStreamer/CMakeLists.txt
@@ -20,8 +20,11 @@ endif()
target_sources(GStreamerReceiver
PRIVATE
- gstqgc.c
- gstqgcvideosinkbin.c
+ gstqgc.cc
+ gstqgcelement.cc
+ gstqgcelements.h
+ gstqgcvideosinkbin.cc
+ gstqgcvideosinkbin.h
GStreamer.cc
GStreamer.h
GstVideoReceiver.cc
@@ -31,8 +34,8 @@ target_sources(GStreamerReceiver
if(IOS)
target_sources(GStreamerReceiver
PRIVATE
- gst_ios_init.h
gst_ios_init.m
+ gst_ios_init.h
)
endif()
@@ -47,6 +50,3 @@ target_link_libraries(GStreamerReceiver
)
target_compile_definitions(QGC PUBLIC QGC_GST_STREAMING)
-if(CMAKE_BUILD_TYPE STREQUAL "Release")
- target_compile_definitions(GStreamerReceiver PRIVATE QGC_INSTALL_RELEASE)
-endif()
diff --git a/src/VideoManager/VideoReceiver/GStreamer/GLVideoItemStub.h b/src/VideoManager/VideoReceiver/GStreamer/GLVideoItemStub.h
index 38d58d468817..63e454b66e70 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/GLVideoItemStub.h
+++ b/src/VideoManager/VideoReceiver/GStreamer/GLVideoItemStub.h
@@ -18,7 +18,5 @@ class GLVideoItemStub : public QQuickItem
public:
GLVideoItemStub(QQuickItem *parent = nullptr) :
- QQuickItem(parent)
- {}
- ~GLVideoItemStub() = default;
+ QQuickItem(parent) {}
};
diff --git a/src/VideoManager/VideoReceiver/GStreamer/GStreamer.cc b/src/VideoManager/VideoReceiver/GStreamer/GStreamer.cc
index 0e2784c98312..e6a172a971e3 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/GStreamer.cc
+++ b/src/VideoManager/VideoReceiver/GStreamer/GStreamer.cc
@@ -7,30 +7,56 @@
*
****************************************************************************/
-
-/**
- * @file
- * @brief QGC Video Streaming Initialization
- * @author Gus Grubba
- */
-
#include "GStreamer.h"
#include "GstVideoReceiver.h"
#include "QGCLoggingCategory.h"
+#ifdef Q_OS_IOS
+#include "gst_ios_init.h"
+#endif
-#include
+#include
-QGC_LOGGING_CATEGORY(GStreamerLog, "GStreamerLog")
-QGC_LOGGING_CATEGORY(GStreamerAPILog, "GStreamerAPILog")
+QGC_LOGGING_CATEGORY(GStreamerLog, "qgc.videomanager.videoreceiver.gstreamer")
+QGC_LOGGING_CATEGORY(GStreamerAPILog, "qgc.videomanager.videoreceiver.gstreamer.api")
-static void qt_gst_log(GstDebugCategory * category,
- GstDebugLevel level,
- const gchar * file,
- const gchar * function,
- gint line,
- GObject * object,
- GstDebugMessage * message,
- gpointer data)
+namespace GStreamer {
+
+G_BEGIN_DECLS
+#ifdef QGC_GST_STATIC_BUILD
+GST_PLUGIN_STATIC_DECLARE(coreelements);
+GST_PLUGIN_STATIC_DECLARE(playback);
+GST_PLUGIN_STATIC_DECLARE(libav);
+GST_PLUGIN_STATIC_DECLARE(rtp);
+GST_PLUGIN_STATIC_DECLARE(rtsp);
+GST_PLUGIN_STATIC_DECLARE(udp);
+GST_PLUGIN_STATIC_DECLARE(videoparsersbad);
+GST_PLUGIN_STATIC_DECLARE(x264);
+GST_PLUGIN_STATIC_DECLARE(rtpmanager);
+GST_PLUGIN_STATIC_DECLARE(isomp4);
+GST_PLUGIN_STATIC_DECLARE(matroska);
+GST_PLUGIN_STATIC_DECLARE(mpegtsdemux);
+GST_PLUGIN_STATIC_DECLARE(opengl);
+GST_PLUGIN_STATIC_DECLARE(tcp);
+GST_PLUGIN_STATIC_DECLARE(asf);
+GST_PLUGIN_STATIC_DECLARE(va);
+#ifdef Q_OS_ANDROID
+GST_PLUGIN_STATIC_DECLARE(androidmedia);
+#elif defined(Q_OS_IOS)
+GST_PLUGIN_STATIC_DECLARE(applemedia);
+#endif
+#endif
+GST_PLUGIN_STATIC_DECLARE(qml6);
+GST_PLUGIN_STATIC_DECLARE(qgc);
+G_END_DECLS
+
+void _QtGstLog(GstDebugCategory *category,
+ GstDebugLevel level,
+ const gchar *file,
+ const gchar *function,
+ gint line,
+ GObject *object,
+ GstDebugMessage *message,
+ gpointer data)
{
Q_UNUSED(data);
@@ -40,7 +66,7 @@ static void qt_gst_log(GstDebugCategory * category,
QMessageLogger log(file, line, function);
- char* object_info = gst_info_strdup_printf("%" GST_PTR_FORMAT, static_cast(object));
+ char *object_info = gst_info_strdup_printf("%" GST_PTR_FORMAT, static_cast(object));
switch (level) {
default:
@@ -66,165 +92,116 @@ static void qt_gst_log(GstDebugCategory * category,
object_info = nullptr;
}
-#if defined(Q_OS_IOS)
-#include "gst_ios_init.h"
-#endif
-
-#include "VideoReceiver.h"
-
-G_BEGIN_DECLS
-// The static plugins we use
-#ifdef QGC_GST_STATIC_BUILD
- GST_PLUGIN_STATIC_DECLARE(coreelements);
- GST_PLUGIN_STATIC_DECLARE(playback);
- GST_PLUGIN_STATIC_DECLARE(libav);
- GST_PLUGIN_STATIC_DECLARE(rtp);
- GST_PLUGIN_STATIC_DECLARE(rtsp);
- GST_PLUGIN_STATIC_DECLARE(udp);
- GST_PLUGIN_STATIC_DECLARE(videoparsersbad);
- GST_PLUGIN_STATIC_DECLARE(x264);
- GST_PLUGIN_STATIC_DECLARE(rtpmanager);
- GST_PLUGIN_STATIC_DECLARE(isomp4);
- GST_PLUGIN_STATIC_DECLARE(matroska);
- GST_PLUGIN_STATIC_DECLARE(mpegtsdemux);
- GST_PLUGIN_STATIC_DECLARE(opengl);
- GST_PLUGIN_STATIC_DECLARE(tcp);
-#if defined(Q_OS_ANDROID)
- GST_PLUGIN_STATIC_DECLARE(androidmedia);
-#elif defined(Q_OS_IOS)
- GST_PLUGIN_STATIC_DECLARE(applemedia);
-#endif
-#endif
- GST_PLUGIN_STATIC_DECLARE(qml6);
- GST_PLUGIN_STATIC_DECLARE(qgc);
-G_END_DECLS
-
-#if (defined(Q_OS_MAC) && defined(QGC_INSTALL_RELEASE)) || defined(Q_OS_WIN) || defined(Q_OS_LINUX)
-static void qgcputenv(const QString& key, const QString& root, const QString& path)
+void _qgcputenv(const QString &key, const QString &root, const QString &path = "")
{
const QString value = root + path;
- qputenv(key.toStdString().c_str(), QByteArray(value.toStdString().c_str()));
+ (void) qputenv(key.toStdString().c_str(), QByteArray(value.toStdString().c_str()));
}
-#endif
-void
-GStreamer::blacklist(VideoDecoderOptions option)
+void blacklist(VideoDecoderOptions option)
{
- GstRegistry* registry = gst_registry_get();
+ GstRegistry* const registry = gst_registry_get();
- if (registry == nullptr) {
+ if (!registry) {
qCCritical(GStreamerLog) << "Failed to get gstreamer registry.";
return;
}
- auto changeRank = [registry](const char* featureName, uint16_t rank) {
- GstPluginFeature* feature = gst_registry_lookup_feature(registry, featureName);
- if (feature == nullptr) {
+ auto changeRank = [registry](const char *featureName, uint16_t rank) {
+ GstPluginFeature* const feature = gst_registry_lookup_feature(registry, featureName);
+ if (!feature) {
qCDebug(GStreamerLog) << "Failed to change ranking of feature. Featuer does not exist:" << featureName;
return;
}
qCDebug(GStreamerLog) << "Changing feature (" << featureName << ") to use rank:" << rank;
gst_plugin_feature_set_rank(feature, rank);
- gst_registry_add_feature(registry, feature);
+ (void) gst_registry_add_feature(registry, feature);
gst_object_unref(feature);
};
- // Set rank for specific features
changeRank("bcmdec", GST_RANK_NONE);
switch (option) {
- case ForceVideoDecoderDefault:
- break;
- case ForceVideoDecoderSoftware:
- for(auto name : {"avdec_h264", "avdec_h265"}) {
- changeRank(name, GST_RANK_PRIMARY + 1);
- }
- break;
- case ForceVideoDecoderVAAPI:
- for(auto name : {"vaapimpeg2dec", "vaapimpeg4dec", "vaapih263dec", "vaapih264dec", "vaapih265dec", "vaapivc1dec"}) {
- changeRank(name, GST_RANK_PRIMARY + 1);
- }
- break;
- case ForceVideoDecoderNVIDIA:
- for(auto name : {"nvh265dec", "nvh265sldec", "nvh264dec", "nvh264sldec"}) {
- changeRank(name, GST_RANK_PRIMARY + 1);
- }
- break;
- case ForceVideoDecoderDirectX3D:
- for(auto name : {"d3d11vp9dec", "d3d11h265dec", "d3d11h264dec"}) {
- changeRank(name, GST_RANK_PRIMARY + 1);
- }
- break;
- case ForceVideoDecoderVideoToolbox:
- changeRank("vtdec", GST_RANK_PRIMARY + 1);
- break;
- default:
- qCWarning(GStreamerLog) << "Can't handle decode option:" << option;
+ case ForceVideoDecoderDefault:
+ break;
+ case ForceVideoDecoderSoftware:
+ for (const char *name : {"avdec_h264", "avdec_h265"}) {
+ changeRank(name, GST_RANK_PRIMARY + 1);
+ }
+ break;
+ case ForceVideoDecoderVAAPI:
+ for (const char *name : {"vaapimpeg2dec", "vaapimpeg4dec", "vaapih263dec", "vaapih264dec", "vaapih265dec", "vaapivc1dec"}) {
+ changeRank(name, GST_RANK_PRIMARY + 1);
+ }
+ break;
+ case ForceVideoDecoderNVIDIA:
+ for (const char *name : {"nvh265dec", "nvh265sldec", "nvh264dec", "nvh264sldec"}) {
+ changeRank(name, GST_RANK_PRIMARY + 1);
+ }
+ break;
+ case ForceVideoDecoderDirectX3D:
+ for (const char *name : {"d3d11vp9dec", "d3d11h265dec", "d3d11h264dec"}) {
+ changeRank(name, GST_RANK_PRIMARY + 1);
+ }
+ break;
+ case ForceVideoDecoderVideoToolbox:
+ changeRank("vtdec", GST_RANK_PRIMARY + 1);
+ break;
+ default:
+ qCWarning(GStreamerLog) << "Can't handle decode option:" << option;
+ break;
}
}
-void
-GStreamer::initialize(int argc, char* argv[], int debuglevel)
+void initialize(int argc, char *argv[], int debuglevel)
{
- qRegisterMetaType("STATUS");
+ (void) qRegisterMetaType("STATUS");
-#ifdef Q_OS_MAC
- #ifdef QGC_INSTALL_RELEASE
- const QString currentDir = QCoreApplication::applicationDirPath();
- qgcputenv("GST_REGISTRY_REUSE_PLUGIN_SCANNER", "no", "");
- qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/libexec/gstreamer-1.0/gst-plugin-scanner");
- qgcputenv("GST_PTP_HELPER_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/libexec/gstreamer-1.0/gst-ptp-helper");
- // qgcputenv("GTK_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current");
- qgcputenv("GIO_EXTRA_MODULES", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gio/modules");
- qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
- qgcputenv("GST_PLUGIN_SYSTEM_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
- qgcputenv("GST_PLUGIN_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
- qgcputenv("GST_PLUGIN_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
- #endif
-#elif defined(Q_OS_WIN)
const QString currentDir = QCoreApplication::applicationDirPath();
- // qgcputenv("GST_PLUGIN_SCANNER", "C:/gstreamer/1.0/msvc_x86_64", "/libexec/gstreamer-1.0/gst-plugin-scanner");
- // qgcputenv("GST_PTP_HELPER_1_0", "C:/gstreamer/1.0/msvc_x86_64", "/libexec/gstreamer-1.0/gst-ptp-helper");
- // qgcputenv("GTK_PATH", "C:/gstreamer/1.0/msvc_x86_64", "");
- // qgcputenv("GIO_EXTRA_MODULES", "C:/gstreamer/1.0/msvc_x86_64", "/lib/gio/modules");
- // qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", "C:/gstreamer/1.0/msvc_x86_64", "/lib/gstreamer-1.0");
- // qgcputenv("GST_PLUGIN_SYSTEM_PATH", "C:/gstreamer/1.0/msvc_x86_64", "/lib/gstreamer-1.0");
- qgcputenv("GST_PLUGIN_PATH_1_0", currentDir, "");
- qgcputenv("GST_PLUGIN_PATH", currentDir, "");
-#elif defined(Q_OS_LINUX)
- // const QString currentDir = QCoreApplication::applicationDirPath();
- // qgcputenv("GST_REGISTRY_REUSE_PLUGIN_SCANNER", "no", "");
- // qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/../lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner");
- // qgcputenv("GST_PTP_HELPER_1_0", currentDir, "/../lib/gstreamer1.0/gstreamer-1.0/gst-ptp-helper");
- // qgcputenv("GTK_PATH", currentDir, "");
- // qgcputenv("GIO_EXTRA_MODULES", currentDir, "/../lib/gio/modules");
- // qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", currentDir, "/../lib");
- // qgcputenv("GST_PLUGIN_SYSTEM_PATH", currentDir, "/../lib");
- // qgcputenv("GST_PLUGIN_PATH_1_0", currentDir, "/../lib");
- // qgcputenv("GST_PLUGIN_PATH", currentDir, "/../lib");
+
+#ifndef QGC_INSTALL_RELEASE
+ qunsetenv("GST_PLUGIN_SYSTEM_PATH_1_0");
+ qunsetenv("GST_PLUGIN_SYSTEM_PATH");
+ qunsetenv("GST_PLUGIN_PATH_1_0");
+ qunsetenv("GST_PLUGIN_PATH");
+ Q_UNUSED(currentDir);
+#elif defined(Q_OS_MAC)
+ _qgcputenv("GST_REGISTRY_REUSE_PLUGIN_SCANNER", "no");
+ _qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/libexec/gstreamer-1.0/gst-plugin-scanner");
+ _qgcputenv("GST_PTP_HELPER_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/libexec/gstreamer-1.0/gst-ptp-helper");
+ _qgcputenv("GIO_EXTRA_MODULES", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gio/modules");
+ _qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
+ _qgcputenv("GST_PLUGIN_SYSTEM_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
+ _qgcputenv("GST_PLUGIN_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
+ _qgcputenv("GST_PLUGIN_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
+#elif defined(Q_OS_WIN)
+ _qgcputenv("GST_REGISTRY_REUSE_PLUGIN_SCANNER", "no");
+ _qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/gstreamer-1.0/gst-plugin-scanner");
+ _qgcputenv("GST_PTP_HELPER_1_0", currentDir, "/gstreamer-1.0/gst-ptp-helper");
+ _qgcputenv("GIO_EXTRA_MODULES", currentDir, "/gio/modules");
+ _qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", currentDir);
+ _qgcputenv("GST_PLUGIN_SYSTEM_PATH", currentDir);
+ _qgcputenv("GST_PLUGIN_PATH_1_0", currentDir);
+ _qgcputenv("GST_PLUGIN_PATH", currentDir);
#endif
- //-- If gstreamer debugging is not configured via environment then use internal QT logging
if (qEnvironmentVariableIsEmpty("GST_DEBUG")) {
gst_debug_set_default_threshold(static_cast(debuglevel));
gst_debug_remove_log_function(gst_debug_log_default);
- gst_debug_add_log_function(qt_gst_log, nullptr, nullptr);
+ gst_debug_add_log_function(_QtGstLog, nullptr, nullptr);
}
- // Initialize GStreamer
-#if defined(Q_OS_IOS)
- //-- iOS specific initialization
+#ifdef Q_OS_IOS
gst_ios_pre_init();
#endif
- GError* error = nullptr;
+ GError *error = nullptr;
if (!gst_init_check(&argc, &argv, &error)) {
- qCCritical(GStreamerLog) << "gst_init_check() failed: " << error->message;
+ qCCritical(GStreamerLog) << "gst_init_check() failed:" << error->message;
g_error_free(error);
}
- // The static plugins we use
#ifdef QGC_GST_STATIC_BUILD
GST_PLUGIN_STATIC_REGISTER(coreelements);
GST_PLUGIN_STATIC_REGISTER(playback);
@@ -240,30 +217,25 @@ GStreamer::initialize(int argc, char* argv[], int debuglevel)
GST_PLUGIN_STATIC_REGISTER(mpegtsdemux);
GST_PLUGIN_STATIC_REGISTER(opengl);
GST_PLUGIN_STATIC_REGISTER(tcp);
-
-#if defined(Q_OS_ANDROID)
+ GST_PLUGIN_STATIC_REGISTER(asf);
+ GST_PLUGIN_STATIC_REGISTER(va);
+#ifdef Q_OS_ANDROID
GST_PLUGIN_STATIC_REGISTER(androidmedia);
#elif defined(Q_OS_IOS)
GST_PLUGIN_STATIC_REGISTER(applemedia);
-#endif
-#endif
-
-#if defined(Q_OS_IOS)
gst_ios_post_init();
#endif
-
+#endif
GST_PLUGIN_STATIC_REGISTER(qml6);
GST_PLUGIN_STATIC_REGISTER(qgc);
}
-void*
-GStreamer::createVideoSink(QObject* parent, QQuickItem* widget)
+void *createVideoSink(QObject *parent, QQuickItem *widget)
{
Q_UNUSED(parent)
- GstElement* sink;
-
- if ((sink = gst_element_factory_make("qgcvideosinkbin", nullptr)) != nullptr) {
+ GstElement* const sink = gst_element_factory_make("qgcvideosinkbin", nullptr);
+ if (sink) {
g_object_set(sink, "widget", widget, NULL);
} else {
qCCritical(GStreamerLog) << "gst_element_factory_make('qgcvideosinkbin') failed";
@@ -272,17 +244,16 @@ GStreamer::createVideoSink(QObject* parent, QQuickItem* widget)
return sink;
}
-void
-GStreamer::releaseVideoSink(void* sink)
+void releaseVideoSink(void *sink)
{
- if (sink != nullptr) {
+ if (sink) {
gst_object_unref(GST_ELEMENT(sink));
}
}
-VideoReceiver*
-GStreamer::createVideoReceiver(QObject* parent)
+VideoReceiver *createVideoReceiver(QObject *parent)
{
- Q_UNUSED(parent)
- return new GstVideoReceiver(nullptr);
+ return new GstVideoReceiver(parent);
+}
+
}
diff --git a/src/VideoManager/VideoReceiver/GStreamer/GStreamer.h b/src/VideoManager/VideoReceiver/GStreamer/GStreamer.h
index 71b185b18f56..e0a9f85c616a 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/GStreamer.h
+++ b/src/VideoManager/VideoReceiver/GStreamer/GStreamer.h
@@ -10,20 +10,26 @@
#pragma once
#include
-#include
-
-#include "Settings/VideoDecoderOptions.h"
Q_DECLARE_LOGGING_CATEGORY(GStreamerLog)
Q_DECLARE_LOGGING_CATEGORY(GStreamerAPILog)
class VideoReceiver;
+class QQuickItem;
+
+namespace GStreamer {
+enum VideoDecoderOptions {
+ ForceVideoDecoderDefault = 0,
+ ForceVideoDecoderSoftware,
+ ForceVideoDecoderNVIDIA,
+ ForceVideoDecoderVAAPI,
+ ForceVideoDecoderDirectX3D,
+ ForceVideoDecoderVideoToolbox,
+};
-class GStreamer {
-public:
- static void blacklist(VideoDecoderOptions option);
- static void initialize(int argc, char* argv[], int debuglevel);
- static void* createVideoSink(QObject* parent, QQuickItem* widget);
- static void releaseVideoSink(void* sink);
- static VideoReceiver* createVideoReceiver(QObject* parent);
+void blacklist(VideoDecoderOptions option);
+void initialize(int argc, char *argv[], int debuglevel);
+void *createVideoSink(QObject *parent, QQuickItem *widget);
+void releaseVideoSink(void *sink);
+VideoReceiver *createVideoReceiver(QObject *parent = nullptr);
};
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.h b/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.h
index 2f86cdb70c6c..b1379bf20c43 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.h
+++ b/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.h
@@ -13,7 +13,9 @@
G_BEGIN_DECLS
-void gst_ios_pre_init(void);
-void gst_ios_post_init(void);
+void gst_ios_pre_init();
+
+/// Lower the ranks of filesrc and giosrc so iosavassetsrc is tried first in gst_element_make_from_uri() for file://
+void gst_ios_post_init();
G_END_DECLS
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.m b/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.m
index 6158e1bca879..76a1f2218268 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.m
+++ b/src/VideoManager/VideoReceiver/GStreamer/gst_ios_init.m
@@ -1,8 +1,23 @@
+/****************************************************************************
+ *
+ * (c) 2009-2024 QGROUNDCONTROL PROJECT
+ *
+ * QGroundControl is licensed according to the terms in the file
+ * COPYING.md in the root of the source code directory.
+ *
+ ****************************************************************************/
+
#import
#import
#include "gst_ios_init.h"
+#define GST_IOS_GIO_MODULE_GNUTLS
+#if defined(GST_IOS_GIO_MODULE_GNUTLS)
+ #include
+ GST_G_IO_MODULE_DECLARE(gnutls);
+#endif
+
G_BEGIN_DECLS
#define GST_G_IO_MODULE_DECLARE(name) \
@@ -13,68 +28,60 @@ extern void G_PASTE(g_io_module_, G_PASTE(name, _load_static)) (void)
G_END_DECLS
-#define GST_IOS_GIO_MODULE_GNUTLS
+void gst_ios_pre_init()
+{
+ const NSString *const resources = [[NSBundle mainBundle] resourcePath];
+ const NSString *const tmp = NSTemporaryDirectory();
+ const NSString *const cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
+ const NSString *const docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
-#if defined(GST_IOS_GIO_MODULE_GNUTLS)
- #include
- GST_G_IO_MODULE_DECLARE(gnutls);
-#endif
+ const gchar *const resources_dir = [resources UTF8String];
+ const gchar *const tmp_dir = [tmp UTF8String];
+ const gchar *const cache_dir = [cache UTF8String];
+ const gchar *const docs_dir = [docs UTF8String];
-void gst_ios_pre_init(void)
-{
- NSString *resources = [[NSBundle mainBundle] resourcePath];
- NSString *tmp = NSTemporaryDirectory();
- NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
- NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
-
- const gchar *resources_dir = [resources UTF8String];
- const gchar *tmp_dir = [tmp UTF8String];
- const gchar *cache_dir = [cache UTF8String];
- const gchar *docs_dir = [docs UTF8String];
- gchar *ca_certificates;
-
- g_setenv ("TMP", tmp_dir, TRUE);
- g_setenv ("TEMP", tmp_dir, TRUE);
- g_setenv ("TMPDIR", tmp_dir, TRUE);
- g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE);
- g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE);
-
- g_setenv ("HOME", docs_dir, TRUE);
- g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE);
- g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE);
- g_setenv ("XDG_CONFIG_HOME", cache_dir, TRUE);
- g_setenv ("XDG_DATA_HOME", resources_dir, TRUE);
- g_setenv ("FONTCONFIG_PATH", resources_dir, TRUE);
-
- ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certificates.crt", NULL);
- g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE);
- g_free (ca_certificates);
+ g_setenv("TMP", tmp_dir, TRUE);
+ g_setenv("TEMP", tmp_dir, TRUE);
+ g_setenv("TMPDIR", tmp_dir, TRUE);
+ g_setenv("XDG_RUNTIME_DIR", resources_dir, TRUE);
+ g_setenv("XDG_CACHE_HOME", cache_dir, TRUE);
+
+ g_setenv("HOME", docs_dir, TRUE);
+ g_setenv("XDG_DATA_DIRS", resources_dir, TRUE);
+ g_setenv("XDG_CONFIG_DIRS", resources_dir, TRUE);
+ g_setenv("XDG_CONFIG_HOME", cache_dir, TRUE);
+ g_setenv("XDG_DATA_HOME", resources_dir, TRUE);
+ g_setenv("FONTCONFIG_PATH", resources_dir, TRUE);
+
+ gchar *const ca_certificates = g_build_filename(resources_dir, "ssl", "certs", "ca-certificates.crt", NULL);
+ g_setenv("CA_CERTIFICATES", ca_certificates, TRUE);
+ g_free(ca_certificates);
}
-void gst_ios_post_init(void)
+void gst_ios_post_init()
{
- GstPluginFeature *plugin;
- GstRegistry *reg;
- /* Lower the ranks of filesrc and giosrc so iosavassetsrc is
- * tried first in gst_element_make_from_uri() for file:// */
-
#if defined(GST_IOS_GIO_MODULE_GNUTLS)
GST_G_IO_MODULE_LOAD(gnutls);
#endif
- reg = gst_registry_get();
- plugin = gst_registry_lookup_feature(reg, "filesrc");
- if (plugin)
- gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY);
- plugin = gst_registry_lookup_feature(reg, "giosrc");
- if (plugin)
- gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY-1);
- if (!gst_registry_lookup_feature(reg, "vtdec_hw")) {
+ GstRegistry *const reg = gst_registry_get();
+ GstPluginFeature *plugin = gst_registry_lookup_feature(reg, "filesrc");
+ if (plugin) {
+ gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY);
+ }
+
+ plugin = gst_registry_lookup_feature(reg, "giosrc");
+ if (plugin) {
+ gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY - 1);
+ }
+
+ if (!gst_registry_lookup_feature(reg, "vtdec_hw")) {
/* Usually there is no vtdec_hw plugin on iOS - in that case
* we are increasing vtdec rank since VideoToolbox on iOS
* tries to use hardware implementation first */
- plugin = gst_registry_lookup_feature(reg, "vtdec");
- if (plugin)
- gst_plugin_feature_set_rank(plugin, GST_RANK_PRIMARY + 1);
+ plugin = gst_registry_lookup_feature(reg, "vtdec");
+ if (plugin) {
+ gst_plugin_feature_set_rank(plugin, GST_RANK_PRIMARY + 1);
+ }
}
}
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgc.c b/src/VideoManager/VideoReceiver/GStreamer/gstqgc.c
deleted file mode 100644
index f8b8cf5d8137..000000000000
--- a/src/VideoManager/VideoReceiver/GStreamer/gstqgc.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
- *
- * (c) 2009-2020 QGROUNDCONTROL PROJECT
- *
- * QGroundControl is licensed according to the terms in the file
- * COPYING.md in the root of the source code directory.
- *
- ****************************************************************************/
-
-/**
- * @file
- * @brief GStreamer plugin for QGC's Video Receiver
- * @author Andrew Voznyts
- * @author Tomaz Canabrava
- */
-
-#include
-
-gboolean gst_qgc_video_sink_bin_plugin_init(GstPlugin *plugin);
-
-static gboolean
-plugin_init(GstPlugin* plugin)
-{
- if (!gst_qgc_video_sink_bin_plugin_init(plugin)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-#define PACKAGE "QGC Video Receiver"
-#define PACKAGE_VERSION "current"
-#define GST_LICENSE "LGPL"
-#define GST_PACKAGE_NAME "GStreamer plugin for QGC's Video Receiver"
-#define GST_PACKAGE_ORIGIN "http://qgroundcontrol.com/"
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
- qgc, "QGC Video Receiver plugin",
- plugin_init, PACKAGE_VERSION,
- GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgc.cc b/src/VideoManager/VideoReceiver/GStreamer/gstqgc.cc
new file mode 100644
index 000000000000..09dc771b85ac
--- /dev/null
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqgc.cc
@@ -0,0 +1,39 @@
+/****************************************************************************
+ *
+ * (c) 2009-2024 QGROUNDCONTROL PROJECT
+ *
+ * QGroundControl is licensed according to the terms in the file
+ * COPYING.md in the root of the source code directory.
+ *
+ ****************************************************************************/
+
+#include "gstqgcelements.h"
+#include "gstqgcvideosinkbin.h"
+
+static gboolean
+plugin_init(GstPlugin *plugin)
+{
+ gboolean ret = FALSE;
+
+ ret |= GST_ELEMENT_REGISTER(qgcvideosinkbin, plugin);
+
+ return ret;
+}
+
+#define PACKAGE "QGC Video Receiver"
+#define VERSION "current"
+#define GST_LICENSE "LGPL"
+#define GST_PACKAGE_NAME "GStreamer plugin for QGC's Video Receiver"
+#define GST_PACKAGE_ORIGIN "https://qgroundcontrol.com/"
+
+GST_PLUGIN_DEFINE(
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ qgc,
+ "QGC Video Receiver Plugin",
+ plugin_init,
+ VERSION,
+ GST_LICENSE,
+ GST_PACKAGE_NAME,
+ GST_PACKAGE_ORIGIN
+)
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgcelement.cc b/src/VideoManager/VideoReceiver/GStreamer/gstqgcelement.cc
new file mode 100644
index 000000000000..68154a64f986
--- /dev/null
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqgcelement.cc
@@ -0,0 +1,11 @@
+#include "gstqgcelements.h"
+#include "gstqgcvideosinkbin.h"
+
+void
+qgc_element_init(GstPlugin *plugin)
+{
+ static gsize res = FALSE;
+ if (g_once_init_enter(&res)) {
+ g_once_init_leave(&res, TRUE);
+ }
+}
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgcelements.h b/src/VideoManager/VideoReceiver/GStreamer/gstqgcelements.h
new file mode 100644
index 000000000000..82befd308cbf
--- /dev/null
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqgcelements.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include
+
+G_BEGIN_DECLS
+
+void qgc_element_init(GstPlugin *plugin);
+
+GST_ELEMENT_REGISTER_DECLARE(qgcvideosinkbin);
+
+G_END_DECLS
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.c b/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.cc
similarity index 59%
rename from src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.c
rename to src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.cc
index 4e26e158f023..994d1db85395 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.c
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.cc
@@ -7,38 +7,19 @@
*
****************************************************************************/
-/**
- * @file
- * @brief GStreamer plugin for QGC's Video Receiver
- * @author Andrew Voznyts
- * @author Tomaz Canabrava
- */
-
-#include
+#include "gstqgcvideosinkbin.h"
+#include "gstqgcelements.h"
+
#include
-#include
GST_DEBUG_CATEGORY_STATIC(gst_qgc_video_sink_bin_debug);
#define GST_CAT_DEFAULT gst_qgc_video_sink_bin_debug
-typedef struct _GstQgcVideoSinkElement GstQgcVideoSinkElement;
-
-typedef struct _GstQgcVideoSinkBin {
- GstBin bin;
- GstElement* glupload;
- GstElement* qmlglsink;
-} GstQgcVideoSinkBin;
-
-typedef struct _GstQgcVideoSinkBinClass {
- GstBinClass parent_class;
-} GstQgcVideoSinkBinClass;
+static void gst_qgc_video_sink_bin_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static void gst_qgc_video_sink_bin_dispose(GObject *object);
-#define GST_TYPE_VIDEO_SINK_BIN (_vsb_get_type())
-#define GST_QGC_VIDEO_SINK_BIN_CAST(obj) ((GstQgcVideoSinkBin *)(obj))
-#define GST_QGC_VIDEO_SINK_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_VIDEO_SINK_BIN, GstQgcVideoSinkBin))
-#define GST_QGC_VIDEO_SINK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_VIDEO_SINK_BIN, GstQgcVideoSinkBinClass))
-#define GST_IS_VIDEO_SINK_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VIDEO_SINK_BIN))
-#define GST_IS_VIDEO_SINK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VIDEO_SINK_BIN))
+static gboolean gst_qgc_video_sink_bin_sink_pad_query(GstPad *pad, GstObject *parent, GstQuery *query);
enum {
PROP_0,
@@ -63,109 +44,59 @@ enum {
#define DEFAULT_PAR_D 1
#define DEFAULT_SYNC TRUE
-static GstBinClass *parent_class;
+#define gst_qgc_video_sink_bin_parent_class parent_class
+G_DEFINE_TYPE(GstQgcVideoSinkBin, gst_qgc_video_sink_bin, GST_TYPE_BIN);
-static void _vsb_init(GTypeInstance *instanceData, void *vsbVoid);
-static void _vsb_dispose(GObject *object);
-static void _vsb_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void _vsb_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static GType _vsb_get_type(void);
-static void _vsb_class_init(void *klass, void *classData);
-
-static gboolean
-_vsb_sink_pad_query(GstPad* pad, GstObject* parent, GstQuery* query)
-{
- GstQgcVideoSinkBin *vsb;
- GstElement* element;
-
- vsb = GST_QGC_VIDEO_SINK_BIN(parent);
-
- switch (GST_QUERY_TYPE(query)) {
- case GST_QUERY_CAPS:
- element = vsb->glupload;
- break;
- case GST_QUERY_CONTEXT:
- element = vsb->qmlglsink;
- break;
- default:
- return gst_pad_query_default (pad, parent, query);
- }
-
- if (element == NULL) {
- GST_ERROR_OBJECT(vsb, "No element found");
- return FALSE;
- }
-
- GstPad* sinkpad = gst_element_get_static_pad(element, "sink");
-
- if (sinkpad == NULL) {
- GST_ERROR_OBJECT(vsb, "No sink pad found");
- return FALSE;
- }
-
- const gboolean ret = gst_pad_query(sinkpad, query);
-
- gst_object_unref(sinkpad);
- sinkpad = NULL;
-
- return ret;
-}
+GST_ELEMENT_REGISTER_DEFINE_WITH_CODE(qgcvideosinkbin, "qgcvideosinkbin", GST_RANK_NONE, GST_TYPE_QGC_VIDEO_SINK_BIN, qgc_element_init(plugin));
static void
-_vsb_init(GTypeInstance *instanceData, void *vsbVoid)
+gst_qgc_video_sink_bin_init(GstQgcVideoSinkBin *vsb)
{
- Q_UNUSED(vsbVoid);
-
- GstQgcVideoSinkBin *vsb;
- vsb = (GstQgcVideoSinkBin *)instanceData;
-
- gboolean initialized = FALSE;
- GstElement* glcolorconvert = NULL;
- GstPad* pad = NULL;
+ (void) vsb;
+ gboolean initialized = FALSE;
+ GstElement *glcolorconvert = NULL;
+ GstPad *pad = NULL;
do {
- if ((vsb->glupload = gst_element_factory_make("glupload", NULL)) == NULL) {
+ if (!(vsb->glupload = gst_element_factory_make("glupload", NULL))) {
GST_ERROR_OBJECT(vsb, "gst_element_factory_make('glupload') failed");
break;
}
- if ((vsb->qmlglsink = gst_element_factory_make("qml6glsink", NULL)) == NULL) {
+ if (!(vsb->qmlglsink = gst_element_factory_make("qml6glsink", NULL))) {
GST_ERROR_OBJECT(vsb, "gst_element_factory_make('qml6glsink') failed");
break;
}
- if ((glcolorconvert = gst_element_factory_make("glcolorconvert", NULL)) == NULL) {
+ if (!(glcolorconvert = gst_element_factory_make("glcolorconvert", NULL))) {
GST_ERROR_OBJECT(vsb, "gst_element_factory_make('glcolorconvert' failed)");
break;
}
- if ((pad = gst_element_get_static_pad(vsb->glupload, "sink")) == NULL) {
+ if (!(pad = gst_element_get_static_pad(vsb->glupload, "sink"))) {
GST_ERROR_OBJECT(vsb, "gst_element_get_static_pad(glupload, 'sink') failed");
break;
}
- gst_object_ref(vsb->glupload);
- gst_object_ref(vsb->qmlglsink);
+ (void) gst_object_ref(vsb->glupload);
+ (void) gst_object_ref(vsb->qmlglsink);
gst_bin_add_many(GST_BIN(vsb), vsb->glupload, glcolorconvert, vsb->qmlglsink, NULL);
- gboolean ret = gst_element_link_many(vsb->glupload, glcolorconvert, vsb->qmlglsink, NULL);
-
+ const gboolean ret = gst_element_link_many(vsb->glupload, glcolorconvert, vsb->qmlglsink, NULL);
glcolorconvert = NULL;
-
if (!ret) {
GST_ERROR_OBJECT(vsb, "gst_element_link_many() failed");
break;
}
- GstPad* ghostpad;
-
- if ((ghostpad = gst_ghost_pad_new("sink", pad)) == NULL) {
+ GstPad *ghostpad = NULL;
+ if (!(ghostpad = gst_ghost_pad_new("sink", pad))) {
GST_ERROR_OBJECT(vsb, "gst_ghost_pad_new('sink') failed");
break;
}
- gst_pad_set_query_function(ghostpad, _vsb_sink_pad_query);
+ gst_pad_set_query_function(ghostpad, gst_qgc_video_sink_bin_sink_pad_query);
if (!gst_element_add_pad(GST_ELEMENT(vsb), ghostpad)) {
GST_ERROR_OBJECT(vsb, "gst_element_add_pad() failed");
@@ -175,23 +106,23 @@ _vsb_init(GTypeInstance *instanceData, void *vsbVoid)
initialized = TRUE;
} while(0);
- if (pad != NULL) {
+ if (pad) {
gst_object_unref(pad);
pad = NULL;
}
- if (glcolorconvert != NULL) {
+ if (glcolorconvert) {
gst_object_unref(glcolorconvert);
glcolorconvert = NULL;
}
if (!initialized) {
- if (vsb->qmlglsink != NULL) {
+ if (vsb->qmlglsink) {
gst_object_unref(vsb->qmlglsink);
vsb->qmlglsink = NULL;
}
- if (vsb->glupload != NULL) {
+ if (vsb->glupload) {
gst_object_unref(vsb->glupload);
vsb->glupload = NULL;
}
@@ -199,31 +130,95 @@ _vsb_init(GTypeInstance *instanceData, void *vsbVoid)
}
static void
-_vsb_dispose(GObject *object)
+gst_qgc_video_sink_bin_class_init(GstQgcVideoSinkBinClass * klass)
{
- GstQgcVideoSinkBin *vsb;
+ GObjectClass *const gobject_klass = reinterpret_cast(klass);
+ GstElementClass *const gstelement_klass = reinterpret_cast(klass);
- vsb = GST_QGC_VIDEO_SINK_BIN(object);
+ parent_class = g_type_class_peek_parent((GstBinClass*)klass);
- if (vsb->qmlglsink != NULL) {
- gst_object_unref(vsb->qmlglsink);
- vsb->qmlglsink = NULL;
+ gobject_klass->dispose = gst_qgc_video_sink_bin_dispose;
+ gobject_klass->get_property = gst_qgc_video_sink_bin_get_property;
+ gobject_klass->set_property = gst_qgc_video_sink_bin_set_property;
+
+ g_object_class_install_property(gobject_klass, PROP_ENABLE_LAST_SAMPLE,
+ g_param_spec_boolean(PROP_ENABLE_LAST_SAMPLE_NAME, "Enable Last Buffer",
+ "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE,
+ static_cast(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property(gobject_klass, PROP_LAST_SAMPLE,
+ g_param_spec_boxed(PROP_LAST_SAMPLE_NAME, "Last Sample",
+ "The last sample received in the sink", GST_TYPE_SAMPLE,
+ static_cast(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property(gobject_klass, PROP_WIDGET,
+ g_param_spec_pointer(PROP_WIDGET_NAME, "QQuickItem",
+ "The QQuickItem to place in the object hierarchy",
+ static_cast(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property(gobject_klass, PROP_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean(PROP_FORCE_ASPECT_RATIO_NAME, "Force aspect ratio",
+ "When enabled, scaling will respect original aspect ratio",
+ DEFAULT_FORCE_ASPECT_RATIO,
+ static_cast(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property(gobject_klass, PROP_PIXEL_ASPECT_RATIO,
+ gst_param_spec_fraction(PROP_PIXEL_ASPECT_RATIO_NAME, "Pixel Aspect Ratio",
+ "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
+ G_MAXINT, 1, 1, 1,
+ static_cast(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property(gobject_klass, PROP_SYNC,
+ g_param_spec_boolean(PROP_SYNC_NAME, "Sync",
+ "Sync on the clock", DEFAULT_SYNC,
+ static_cast(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ gst_element_class_set_static_metadata(gstelement_klass,
+ "QGC Video Sink Bin", "Sink/Video/Bin",
+ "Video rendering for QGC",
+ "Andrew Voznytsa , Tomaz Canabrava ");
+}
+
+static gboolean
+gst_qgc_video_sink_bin_sink_pad_query(GstPad *pad, GstObject *parent, GstQuery *query)
+{
+ GstQgcVideoSinkBin *const vsb = GST_QGC_VIDEO_SINK_BIN(parent);
+ GstElement *element = NULL;
+
+ switch (GST_QUERY_TYPE(query)) {
+ case GST_QUERY_CAPS:
+ element = vsb->glupload;
+ break;
+ case GST_QUERY_CONTEXT:
+ element = vsb->qmlglsink;
+ break;
+ default:
+ return gst_pad_query_default(pad, parent, query);
}
- if (vsb->glupload != NULL) {
- gst_object_unref(vsb->glupload);
- vsb->glupload = NULL;
+ if (!element) {
+ GST_ERROR_OBJECT(vsb, "No element found");
+ return FALSE;
}
- G_OBJECT_CLASS(parent_class)->dispose(object);
+ GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
+ if (!sinkpad) {
+ GST_ERROR_OBJECT(vsb, "No sink pad found");
+ return FALSE;
+ }
+
+ const gboolean ret = gst_pad_query(sinkpad, query);
+
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ return ret;
}
static void
-_vsb_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
- GstQgcVideoSinkBin *vsb;
-
- vsb = GST_QGC_VIDEO_SINK_BIN(object);
+ GstQgcVideoSinkBin *const vsb = GST_QGC_VIDEO_SINK_BIN(object);
switch (prop_id) {
case PROP_ENABLE_LAST_SAMPLE:
@@ -279,11 +274,9 @@ _vsb_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *psp
}
static void
-_vsb_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+gst_qgc_video_sink_bin_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- GstQgcVideoSinkBin *vsb;
-
- vsb = GST_QGC_VIDEO_SINK_BIN(object);
+ GstQgcVideoSinkBin *const vsb = GST_QGC_VIDEO_SINK_BIN(object);
switch (prop_id) {
case PROP_ENABLE_LAST_SAMPLE:
@@ -307,88 +300,20 @@ _vsb_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpe
}
}
-static GType
-_vsb_get_type(void)
-{
- static GType _vsb_type = 0;
-
- if (!_vsb_type) {
- static const GTypeInfo _vsb_info = {
- sizeof(GstQgcVideoSinkBinClass),
- NULL,
- NULL,
- (GClassInitFunc)_vsb_class_init,
- NULL,
- NULL,
- sizeof(GstQgcVideoSinkBin),
- 0,
- (GInstanceInitFunc)_vsb_init,
- NULL};
-
- _vsb_type = g_type_register_static(GST_TYPE_BIN, "GstQgcVideoSinkBin", &_vsb_info, (GTypeFlags)0);
- }
-
- return _vsb_type;
-}
-
static void
-_vsb_class_init(void *klass, void *classData)
+gst_qgc_video_sink_bin_dispose(GObject *object)
{
- Q_UNUSED(classData);
-
- GObjectClass *gobject_klass;
- GstElementClass *gstelement_klass;
-
- gobject_klass = (GObjectClass *)klass;
- gstelement_klass = (GstElementClass *)klass;
-
- parent_class = g_type_class_peek_parent(klass);
-
- gobject_klass->dispose = _vsb_dispose;
- gobject_klass->get_property = _vsb_get_property;
- gobject_klass->set_property = _vsb_set_property;
-
- g_object_class_install_property(gobject_klass, PROP_ENABLE_LAST_SAMPLE,
- g_param_spec_boolean(PROP_ENABLE_LAST_SAMPLE_NAME, "Enable Last Buffer",
- "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE,
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
-
- g_object_class_install_property(gobject_klass, PROP_LAST_SAMPLE,
- g_param_spec_boxed(PROP_LAST_SAMPLE_NAME, "Last Sample",
- "The last sample received in the sink", GST_TYPE_SAMPLE,
- (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+ GstQgcVideoSinkBin *const vsb = GST_QGC_VIDEO_SINK_BIN(object);
- g_object_class_install_property(gobject_klass, PROP_WIDGET,
- g_param_spec_pointer(PROP_WIDGET_NAME, "QQuickItem",
- "The QQuickItem to place in the object hierarchy",
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
-
- g_object_class_install_property(gobject_klass, PROP_FORCE_ASPECT_RATIO,
- g_param_spec_boolean(PROP_FORCE_ASPECT_RATIO_NAME, "Force aspect ratio",
- "When enabled, scaling will respect original aspect ratio",
- DEFAULT_FORCE_ASPECT_RATIO,
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
-
- g_object_class_install_property(gobject_klass, PROP_PIXEL_ASPECT_RATIO,
- gst_param_spec_fraction(PROP_PIXEL_ASPECT_RATIO_NAME, "Pixel Aspect Ratio",
- "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
- G_MAXINT, 1, 1, 1,
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
-
- g_object_class_install_property(gobject_klass, PROP_SYNC,
- g_param_spec_boolean(PROP_SYNC_NAME, "Sync",
- "Sync on the clock", DEFAULT_SYNC,
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+ if (vsb->qmlglsink) {
+ gst_object_unref(vsb->qmlglsink);
+ vsb->qmlglsink = NULL;
+ }
- gst_element_class_set_static_metadata(gstelement_klass,
- "QGC Video Sink Bin", "Sink/Video/Bin",
- "Video rendering for QGC",
- "Andrew Voznytsa , Tomaz Canabrava ");
-}
+ if (vsb->glupload) {
+ gst_object_unref(vsb->glupload);
+ vsb->glupload = NULL;
+ }
-gboolean
-gst_qgc_video_sink_bin_plugin_init(GstPlugin *plugin)
-{
- GST_DEBUG_CATEGORY_INIT(gst_qgc_video_sink_bin_debug, "qgcvideosinkbin", 0, "QGC Video Sink Bin");
- return gst_element_register(plugin, "qgcvideosinkbin", GST_RANK_NONE, GST_TYPE_VIDEO_SINK_BIN);
+ G_OBJECT_CLASS(parent_class)->dispose(object);
}
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.h b/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.h
new file mode 100644
index 000000000000..8bd3698685fb
--- /dev/null
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqgcvideosinkbin.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+ *
+ * (c) 2009-2024 QGROUNDCONTROL PROJECT
+ *
+ * QGroundControl is licensed according to the terms in the file
+ * COPYING.md in the root of the source code directory.
+ *
+ ****************************************************************************/
+
+#pragma once
+
+#include
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_QGC_VIDEO_SINK_BIN (gst_qgc_video_sink_bin_get_type())
+G_DECLARE_FINAL_TYPE (GstQgcVideoSinkBin, gst_qgc_video_sink_bin, GST, QGC_VIDEO_SINK_BIN, GstBin)
+
+struct _GstQgcVideoSinkBin {
+ GstBin bin;
+ GstElement *glupload;
+ GstElement *qmlglsink;
+};
+
+struct _GstQgcVideoSinkBinClass {
+ GstBinClass parent_class;
+};
+
+GST_ELEMENT_REGISTER_DECLARE(qgcvideosinkbin);
+
+G_END_DECLS
diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt b/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt
index dcb51a009beb..8610b3e0df4e 100644
--- a/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt
+++ b/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt
@@ -1,30 +1,51 @@
-find_package(GStreamer REQUIRED COMPONENTS Allocators Audio Codecparsers Controller Mpegts Net Pbutils Riff Rtp Rtsp Sdp Tag OPTIONAL_COMPONENTS Va Photography X11 EGL Wayland)
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
+find_package(GStreamer REQUIRED COMPONENTS Allocators Audio Codecparsers Controller Fft Mpegts Net Pbutils Riff Rtp Rtsp Sdp Tag OPTIONAL_COMPONENTS Photography Prototypes Va X11 EGL Wayland)
+
+qt_add_library(gstqml6gl STATIC)
-# Use Latest Revisions for each minor version: 1.16.3, 1.18.6, 1.20.7, 1.22.12, 1.24.7
-string(REPLACE "." ";" GST_VERSION_LIST ${GStreamer_VERSION})
-list(GET GST_VERSION_LIST 0 GST_VERSION_MAJOR)
-list(GET GST_VERSION_LIST 1 GST_VERSION_MINOR)
-list(GET GST_VERSION_LIST 2 GST_VERSION_PATCH)
-cmake_print_variables(GST_VERSION_MAJOR GST_VERSION_MINOR GST_VERSION_PATCH)
+target_link_libraries(gstqml6gl
+ PRIVATE
+ Qt6::GuiPrivate
+ PUBLIC
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Qml
+ Qt6::Quick
+ GStreamer::GStreamer
+ GStreamer::Allocators
+ GStreamer::Audio
+ GStreamer::Codecparsers
+ GStreamer::Controller
+ GStreamer::Fft
+ GStreamer::Mpegts
+ GStreamer::Net
+ GStreamer::Pbutils
+ GStreamer::Riff
+ GStreamer::Rtp
+ GStreamer::Rtsp
+ GStreamer::Sdp
+ GStreamer::Tag
+)
-if(GST_VERSION_MINOR EQUAL 16)
- set(GST_VERSION_PATCH 3)
-elseif(GST_VERSION_MINOR EQUAL 18)
- set(GST_VERSION_PATCH 6)
-elseif(GST_VERSION_MINOR EQUAL 20)
- set(GST_VERSION_PATCH 7)
-elseif(GST_VERSION_MINOR EQUAL 22)
- set(GST_VERSION_PATCH 12)
-elseif(GST_VERSION_MINOR EQUAL 24)
- set(GST_VERSION_PATCH 7)
+# Photography not found on ubuntu 20.04?
+if(GStreamer_Photography_FOUND)
+ target_link_libraries(gstqml6gl PUBLIC GStreamer::Photography)
endif()
-set(GST_PLUGINS_VERSION ${GST_VERSION_MAJOR}.${GST_VERSION_MINOR}.${GST_VERSION_PATCH})
-cmake_print_variables(GST_PLUGINS_VERSION)
+if(GStreamer_Prototypes_FOUND)
+ target_link_libraries(gstqml6gl PUBLIC GStreamer::Prototypes)
+endif()
+if(GStreamer_Va_FOUND)
+ target_link_libraries(gstqml6gl PUBLIC GStreamer::Va)
+endif()
+
+################################################################################
+
+# TODO: Don't Download & Build if gstreamer1.0-qt6 was found
if(GStreamer_VERSION VERSION_GREATER_EQUAL 1.22)
FetchContent_Declare(gstreamer_good_plugins
- # https://gitlab.freedesktop.org/gstreamer/gstreamer/-/archive/${GST_PLUGINS_VERSION}/gstreamer-${GST_PLUGINS_VERSION}.zip?path=subprojects/gst-plugins-good/ext/qt6
+ # URL https://gitlab.freedesktop.org/gstreamer/gstreamer/-/archive/${GStreamer_VERSION}/gstreamer-${GStreamer_VERSION}.zip?path=subprojects/gst-plugins-good/ext/qt6
URL https://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-${GST_PLUGINS_VERSION}.tar.xz
DOWNLOAD_EXTRACT_TIMESTAMP true
)
@@ -50,77 +71,31 @@ file(GLOB gstqml6gl_SRCS
${QGC_GST_QT6_PLUGIN_PATH}/*.cc
${QGC_GST_QT6_PLUGIN_PATH}/*.h
)
-qt_add_library(gstqml6gl STATIC ${gstqml6gl_SRCS})
+target_sources(gstqml6gl PRIVATE ${gstqml6gl_SRCS})
target_include_directories(gstqml6gl PUBLIC ${QGC_GST_QT6_PLUGIN_PATH})
-find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
-
-target_link_libraries(gstqml6gl
- PRIVATE
- Qt6::GuiPrivate
- PUBLIC
- Qt6::Core
- Qt6::Gui
- Qt6::Qml
- Qt6::Quick
- GStreamer::GStreamer
- GStreamer::Allocators
- GStreamer::Audio
- GStreamer::Codecparsers
- GStreamer::Controller
- GStreamer::Mpegts
- GStreamer::Net
- GStreamer::Pbutils
- GStreamer::Riff
- GStreamer::Rtp
- GStreamer::Rtsp
- GStreamer::Sdp
- GStreamer::Tag
-)
-
-# Photography not found on ubuntu 20.04?
-if(GStreamer_Photography_FOUND)
- target_link_libraries(gstqml6gl PUBLIC GStreamer::Photography)
-endif()
-
-if(GStreamer_Va_FOUND)
- target_link_libraries(gstqml6gl PUBLIC GStreamer::Va)
-endif()
+################################################################################
if(GStreamer_X11_FOUND)
- # X11, XCB, X11_XCB, GLX
target_link_libraries(gstqml6gl PUBLIC GStreamer::X11)
target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_X11)
endif()
if(GStreamer_EGL_FOUND)
- # EGL
target_link_libraries(gstqml6gl PUBLIC GStreamer::EGL)
target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_EGLFS)
endif()
if(GStreamer_Wayland_FOUND)
- # find_package(Wayland COMPONENTS Client Cursor Egl)
- # find_package(WaylandProtocols)
- # find_package(WaylandScanner)
- find_package(Qt6 COMPONENTS WaylandClient)
- if(Qt6WaylandClient_FOUND)
- target_link_libraries(gstqml6gl PUBLIC GStreamer::Wayland Qt6::WaylandClient)
- target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_WAYLAND)
- endif()
+ target_link_libraries(gstqml6gl PUBLIC GStreamer::Wayland)
+ target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_WAYLAND)
endif()
if(ANDROID)
- # GLESv2, egl
target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_ANDROID)
elseif(WIN32)
- # GDI32, egl, GLESv2
- find_package(OpenGL)
- if(OpenGL_FOUND)
- target_link_libraries(gstqml6gl PUBLIC OpenGL::GL)
- target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_WIN32)
- endif()
+ target_compile_definitions(gstqml6gl PRIVATE HAVE_QT_WIN32)
elseif(MACOS)
# appleframeworks
# Foundation, QuartzCore, CoreFoundation
@@ -138,6 +113,8 @@ target_compile_definitions(gstqml6gl
QT_QPA_HEADER=
)
+################################################################################
+
if(EXISTS "${QGC_GST_QT6_PLUGIN_PATH}/resources.qrc")
find_package(Qt6 REQUIRED COMPONENTS ShaderTools)
@@ -171,6 +148,8 @@ if(EXISTS "${QGC_GST_QT6_PLUGIN_PATH}/resources.qrc")
)
endif()
+################################################################################
+
if(UNIX)
target_compile_options(gstqml6gl
PRIVATE
@@ -180,123 +159,7 @@ if(UNIX)
)
endif()
-# gstva, gstasf
-set(GST_TARGET_PLUGINS
- gstcoreelements
- gstisomp4
- gstlibav
- gstmatroska
- gstmpegtsdemux
- gstopengl
- gstplayback
- gstrtp
- gstrtpmanager
- gstrtsp
- gstsdpelem
- gsttcp
- gstudp
- gstvideoparsersbad
- gstx264
-)
-if(ANDROID)
- list(APPEND GST_TARGET_PLUGINS gstandroidmedia)
-elseif(IOS)
- list(APPEND GST_TARGET_PLUGINS gstapplemedia)
-endif()
-
-find_package(PkgConfig QUIET)
-if(PkgConfig_FOUND)
- pkg_check_modules(GST_PLUGINS IMPORTED_TARGET ${GST_TARGET_PLUGINS})
- if(GST_PLUGINS_FOUND)
- target_link_libraries(gstqml6gl PUBLIC PkgConfig::GST_PLUGINS)
- if(WIN32)
- # install(FILES ${GST_PLUGINS_LIBRARIES} DESTINATION ${CMAKE_INSTALL_BINDIR})
- elseif(LINUX)
- install(FILES ${GST_PLUGINS_LIBRARIES} DESTINATION ${CMAKE_INSTALL_LIBDIR})
- endif()
- endif()
-
- pkg_check_modules(GSTREAMER_PLUGINS_BASE IMPORTED_TARGET gstreamer-plugins-base-1.0)
- if(GSTREAMER_PLUGINS_BASE_FOUND)
- target_link_libraries(gstqml6gl PUBLIC PkgConfig::GSTREAMER_PLUGINS_BASE)
- endif()
-endif()
-
-if(NOT GST_PLUGINS_FOUND)
- foreach(plugin IN LISTS GST_TARGET_PLUGINS)
- find_library(GStreamer_${plugin}_LIBRARY
- NAMES ${plugin}
- PATHS
- ${GSTREAMER_PREFIX}/lib
- ${GSTREAMER_PREFIX}/lib/gstreamer-1.0
- ${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu
- ${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu/gstreamer-1.0
- ${GSTREAMER_PREFIX}/Versions/Current/lib
- ${GSTREAMER_PREFIX}/Versions/Current/lib/gstreamer-1.0
- )
- if(GStreamer_${plugin}_LIBRARY)
- cmake_print_variables(GStreamer_${plugin}_LIBRARY)
- target_link_libraries(gstqml6gl PUBLIC ${GStreamer_${plugin}_LIBRARY})
- if(WIN32)
- # install(FILES ${GStreamer_${plugin}_LIBRARY} DESTINATION ${CMAKE_INSTALL_BINDIR})
- elseif(LINUX)
- install(FILES ${GStreamer_${plugin}_LIBRARY} DESTINATION ${CMAKE_INSTALL_LIBDIR})
- endif()
- endif()
- endforeach()
-
- if(ANDROID)
- target_include_directories(gstqml6gl
- PUBLIC
- ${GSTREAMER_PREFIX}/include/gstreamer-1.0
- ${GSTREAMER_PREFIX}/include/glib-2.0
- ${GSTREAMER_PREFIX}/lib/glib-2.0/include
- ${GSTREAMER_PREFIX}/lib/graphene-1.0/include
- ${GSTREAMER_PREFIX}/lib/gstreamer-1.0/include
- ${GSTREAMER_PREFIX}/include
- )
-
- find_package(FFMPEG REQUIRED COMPONENTS avcodec avfilter avformat avutil swresample)
- if(FFMPEG_FOUND)
- target_link_libraries(gstqml6gl PUBLIC ${FFMPEG_LIBRARIES})
- target_include_directories(gstqml6gl PUBLIC ${FFMPEG_INCLUDE_DIRS})
- endif()
-
- find_package(BZip2)
- if(BZIP2_FOUND)
- target_link_libraries(gstqml6gl PUBLIC BZip2::BZip2)
- endif()
-
- find_library(graphene_LIBRARY graphene-1.0)
- if(graphene_LIBRARY)
- target_link_libraries(gstqml6gl PUBLIC ${graphene_LIBRARY})
- endif()
-
- find_library(x264_LIBRARY x264)
- if(x264_LIBRARY)
- target_link_libraries(gstqml6gl PUBLIC ${x264_LIBRARY})
- endif()
-
- find_package(JPEG)
- if(JPEG_FOUND)
- target_link_libraries(gstqml6gl PUBLIC JPEG::JPEG)
- endif()
-
- find_package(PNG)
- if(PNG_FOUND)
- target_link_libraries(gstqml6gl PUBLIC PNG::PNG)
- endif()
-
- endif()
-endif()
-
-if(ANDROID)
- target_link_options(gstqml6gl PUBLIC "-Wl,-Bsymbolic")
-endif()
-
-if(QGC_GST_STATIC_BUILD)
- target_compile_definitions(gstqml6gl PUBLIC QGC_GST_STATIC_BUILD)
-endif()
+################################################################################
if(LINUX)
install(DIRECTORY ${GSTREAMER_PREFIX}/lib/x86_64-linux-gnu/gstreamer1.0 DESTINATION ${CMAKE_INSTALL_LIBDIR})
@@ -327,3 +190,5 @@ if(WIN32)
file(GLOB GST_WIN_PLUGINS ${GST_WIN_PLUGINS_PATH})
install(FILES ${GST_WIN_PLUGINS} DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
+
+################################################################################
diff --git a/src/VideoManager/VideoReceiver/QtMultimedia/CMakeLists.txt b/src/VideoManager/VideoReceiver/QtMultimedia/CMakeLists.txt
index 76fbd8638a72..7db25fef5568 100644
--- a/src/VideoManager/VideoReceiver/QtMultimedia/CMakeLists.txt
+++ b/src/VideoManager/VideoReceiver/QtMultimedia/CMakeLists.txt
@@ -18,13 +18,13 @@ target_sources(QtMultimediaReceiver
target_link_libraries(QtMultimediaReceiver
PRIVATE
+ Qt6::Multimedia
Qt6::MultimediaQuickPrivate
Qt6::Quick
QGC
Utilities
PUBLIC
Qt6::Core
- Qt6::Multimedia
VideoReceiver
)
diff --git a/src/VideoManager/VideoReceiver/QtMultimedia/UVCReceiver.cc b/src/VideoManager/VideoReceiver/QtMultimedia/UVCReceiver.cc
index fe0167fb38ee..0c9f430dd6f5 100644
--- a/src/VideoManager/VideoReceiver/QtMultimedia/UVCReceiver.cc
+++ b/src/VideoManager/VideoReceiver/QtMultimedia/UVCReceiver.cc
@@ -92,5 +92,5 @@ void UVCReceiver::_checkPermission()
bool UVCReceiver::enabled()
{
- return (QMediaDevices::videoInputs().count() > 0);
+ return !QMediaDevices::videoInputs().isEmpty();
}
diff --git a/tools/setup/install-dependencies-debian.sh b/tools/setup/install-dependencies-debian.sh
index 5213a1a04ed4..fe12e04d8edd 100755
--- a/tools/setup/install-dependencies-debian.sh
+++ b/tools/setup/install-dependencies-debian.sh
@@ -78,9 +78,13 @@ DEBIAN_FRONTEND=noninteractive apt -y --quiet install \
gstreamer1.0-vaapi \
gstreamer1.0-x
+if apt-cache show gstreamer1.0-qt6 >/dev/null 2>&1 && apt-cache show gstreamer1.0-qt6 2>/dev/null | grep -q "^Package: gstreamer1.0-qt6"; then
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --quiet gstreamer1.0-qt6
+
# Additional
DEBIAN_FRONTEND=noninteractive apt -y --quiet install \
flite1-dev \
+ intel-media-va-driver \
libasound2-dev \
libass-dev \
libdrm-dev \
@@ -88,6 +92,8 @@ DEBIAN_FRONTEND=noninteractive apt -y --quiet install \
libexiv2-dev \
libgbm-dev \
libgl1-mesa-dev \
+ libgl-dev \
+ libglx-dev \
libgles2-mesa-dev \
libglu1-mesa-dev \
libglfw3-dev \