@@ -623,7 +623,6 @@ macro(_qgc_discover_ios_sdk)
623623 set (GSTREAMER_PLUGIN_PATH "${_xcfw_slice_dir} " )
624624
625625 _gst_normalize_and_validate_root ()
626- return ()
627626 endif ()
628627
629628 # ── Classic .framework path ───────────────────────────────────────────────
@@ -652,11 +651,33 @@ macro(_qgc_discover_ios_sdk)
652651 endif ()
653652 endforeach ()
654653 endif ()
654+ # 1.28+ embeds everything in the framework binary — no lib/ subdir exists.
655+ if (NOT EXISTS "${GSTREAMER_LIB_PATH} " )
656+ set (GSTREAMER_LIB_PATH "${GStreamer_ROOT_DIR} " )
657+ set (GSTREAMER_PLUGIN_PATH "${GStreamer_ROOT_DIR} " )
658+ endif ()
655659
656- _qgc_find_apple_pkg_config (PKG_CONFIG_EXECUTABLE )
657- _gst_configure_pkg_config (
658- LIBDIR "${GSTREAMER_LIB_PATH} /pkgconfig" "${GSTREAMER_PLUGIN_PATH} /pkgconfig"
659- )
660+ # When no pkgconfig dir is present the framework is a single fat binary (1.28+
661+ # Cerbero layout); reuse the xcframework target-creation path which already handles
662+ # this: no pkg-config queries, direct link of the binary, system framework deps.
663+ if (NOT EXISTS "${GSTREAMER_LIB_PATH} /pkgconfig" )
664+ # The framework binary lives at Versions/1.0/<FrameworkName> (= GStreamer_ROOT_DIR/GStreamer).
665+ set (GSTREAMER_XCFRAMEWORK_PATH "${GSTREAMER_FRAMEWORK_PATH} " )
666+ set (GSTREAMER_XCFRAMEWORK_LIB "${GStreamer_ROOT_DIR} /GStreamer" )
667+ set (GSTREAMER_INCLUDE_PATH "${GSTREAMER_FRAMEWORK_PATH} /Headers" )
668+ # Point synthetic lib/plugin paths at the root so downstream existence checks pass.
669+ set (GSTREAMER_LIB_PATH "${GStreamer_ROOT_DIR} " )
670+ set (GSTREAMER_PLUGIN_PATH "${GStreamer_ROOT_DIR} " )
671+ set (GStreamer_USE_XCFRAMEWORK ON )
672+ _gst_normalize_and_validate_root ()
673+ endif ()
674+
675+ if (NOT GStreamer_USE_XCFRAMEWORK) # xcframework has no .pc files; target already created
676+ _qgc_find_apple_pkg_config (PKG_CONFIG_EXECUTABLE )
677+ _gst_configure_pkg_config (
678+ LIBDIR "${GSTREAMER_LIB_PATH} /pkgconfig" "${GSTREAMER_PLUGIN_PATH} /pkgconfig"
679+ )
680+ endif ()
660681endmacro ()
661682
662683# Dispatch to the appropriate platform discovery macro
@@ -756,8 +777,12 @@ if(NOT DEFINED GSTREAMER_EXTRA_DEPS)
756777 endif ()
757778endif ()
758779
780+ # Default plugin set assumes the videoconvert→appsink rendering path used everywhere.
781+ # The base opengl / d3d11 plugins are kept because GStreamer auto-plugs gldownload /
782+ # d3d11download when hardware decoders produce GPU memory.
759783if (NOT DEFINED GSTREAMER_PLUGINS)
760784 set (GSTREAMER_PLUGINS
785+ app
761786 coreelements
762787 isomp4
763788 libav
@@ -775,15 +800,12 @@ if(NOT DEFINED GSTREAMER_PLUGINS)
775800 udp
776801 videoparsersbad
777802 vpx
803+ # gst >=1.22 split: only the one matching the SDK gets a target; #ifdef in GStreamer.cc picks it.
804+ videoconvertscale
805+ videoconvert
806+ videoscale
778807 )
779- # Deferred on Linux — actual version may differ from the minimum (see finalization below)
780- if (NOT LINUX )
781- if (GStreamer_FIND_VERSION VERSION_GREATER_EQUAL "1.22" )
782- list (APPEND GSTREAMER_PLUGINS videoconvertscale)
783- else ()
784- list (APPEND GSTREAMER_PLUGINS videoconvert videoscale)
785- endif ()
786- endif ()
808+ # Deferred for all platforms — GStreamer_VERSION is populated after find_package(GStreamer) below.
787809 if (ANDROID )
788810 list (APPEND GSTREAMER_PLUGINS androidmedia dav1d)
789811 elseif (APPLE )
@@ -840,11 +862,14 @@ if(GStreamer_USE_XCFRAMEWORK)
840862 target_link_libraries (GStreamer::GStreamer INTERFACE
841863 GStreamer_static
842864 )
843- target_include_directories (GStreamer::GStreamer INTERFACE
844- "${GSTREAMER_INCLUDE_PATH} "
845- "${GSTREAMER_INCLUDE_PATH} /gstreamer-1.0"
846- "${GSTREAMER_INCLUDE_PATH} /glib-2.0"
847- )
865+ # iOS .framework has flat Headers/; macOS-style installs have the gstreamer-1.0 /
866+ # glib-2.0 subdirs. Add only what exists — INTERFACE_INCLUDE_DIRECTORIES is validated.
867+ target_include_directories (GStreamer::GStreamer INTERFACE "${GSTREAMER_INCLUDE_PATH} " )
868+ foreach (_inc_sub IN ITEMS gstreamer-1.0 glib-2.0)
869+ if (IS_DIRECTORY "${GSTREAMER_INCLUDE_PATH} /${_inc_sub} " )
870+ target_include_directories (GStreamer::GStreamer INTERFACE "${GSTREAMER_INCLUDE_PATH} /${_inc_sub} " )
871+ endif ()
872+ endforeach ()
848873 # System frameworks required by GStreamer on iOS.
849874 find_library (_xcfw_foundation Foundation REQUIRED )
850875 find_library (_xcfw_avfoundation AVFoundation REQUIRED )
@@ -1052,15 +1077,6 @@ foreach(plugin IN LISTS GSTREAMER_PLUGINS)
10521077 endif ()
10531078endforeach ()
10541079
1055- if (LINUX AND NOT "videoconvertscale" IN_LIST GSTREAMER_PLUGINS
1056- AND NOT "videoconvert" IN_LIST GSTREAMER_PLUGINS)
1057- if (GStreamer_VERSION VERSION_GREATER_EQUAL "1.22" )
1058- list (APPEND GSTREAMER_PLUGINS videoconvertscale)
1059- else ()
1060- list (APPEND GSTREAMER_PLUGINS videoconvert videoscale)
1061- endif ()
1062- endif ()
1063-
10641080if (NOT GStreamer_USE_STATIC_LIBS AND NOT GStreamer_USE_XCFRAMEWORK AND EXISTS "${GSTREAMER_PLUGIN_PATH} " )
10651081 set (_gst_missing_plugins)
10661082 if (WIN32 )
@@ -1084,7 +1100,18 @@ if(NOT GStreamer_USE_STATIC_LIBS AND NOT GStreamer_USE_XCFRAMEWORK AND EXISTS "$
10841100 endif ()
10851101 endforeach ()
10861102 list (REMOVE_DUPLICATES _gst_available_basenames)
1103+ # videoconvert(scale)/videoscale alternate — only one ships per gst version; don't warn on the absent ones.
1104+ set (_gst_alternate_satisfied FALSE )
1105+ if ("videoconvertscale" IN_LIST _gst_available_basenames
1106+ OR ("videoconvert" IN_LIST _gst_available_basenames
1107+ AND "videoscale" IN_LIST _gst_available_basenames))
1108+ set (_gst_alternate_satisfied TRUE )
1109+ endif ()
10871110 foreach (_plugin IN LISTS GSTREAMER_PLUGINS)
1111+ if (_gst_alternate_satisfied
1112+ AND _plugin MATCHES "^(videoconvertscale|videoconvert|videoscale)$" )
1113+ continue ()
1114+ endif ()
10881115 if (NOT _plugin IN_LIST _gst_available_basenames)
10891116 list (APPEND _gst_missing_plugins "${_plugin} " )
10901117 endif ()
@@ -1096,16 +1123,76 @@ if(NOT GStreamer_USE_STATIC_LIBS AND NOT GStreamer_USE_XCFRAMEWORK AND EXISTS "$
10961123 endif ()
10971124endif ()
10981125
1099- if (GStreamer_VERSION AND TARGET GStreamer::GStreamer )
1126+ if (GStreamer_VERSION)
11001127 string (REGEX MATCH "^([0-9]+)\\ .([0-9]+)" _gst_ver_match "${GStreamer_VERSION} " )
11011128 if (_gst_ver_match)
1102- target_compile_definitions (GStreamer::GStreamer INTERFACE
1103- QGC_GST_BUILD_VERSION_MAJOR=${CMAKE_MATCH_1}
1104- QGC_GST_BUILD_VERSION_MINOR=${CMAKE_MATCH_2}
1105- )
1129+ # Mobile (iOS/Android) builds consume GStreamerMobile (alias GStreamer::mobile) instead
1130+ # of GStreamer::GStreamer, so propagate the version defines to whichever exists.
1131+ foreach (_gst_target IN ITEMS GStreamer::GStreamer GStreamerMobile)
1132+ if (TARGET ${_gst_target} )
1133+ # target_compile_definitions can't be called on ALIAS targets — resolve first.
1134+ get_target_property (_gst_aliased ${_gst_target} ALIASED_TARGET )
1135+ if (_gst_aliased)
1136+ set (_gst_real ${_gst_aliased} )
1137+ else ()
1138+ set (_gst_real ${_gst_target} )
1139+ endif ()
1140+ target_compile_definitions (${_gst_real} INTERFACE
1141+ QGC_GST_BUILD_VERSION_MAJOR=${CMAKE_MATCH_1}
1142+ QGC_GST_BUILD_VERSION_MINOR=${CMAKE_MATCH_2}
1143+ )
1144+ endif ()
1145+ endforeach ()
11061146 endif ()
11071147endif ()
11081148
1149+ # GstVideoOrientationMeta is officially in 1.26+, but bundled iOS/Android SDKs sometimes
1150+ # strip it. Feature-test the actual header instead of trusting the version number.
1151+ include (CheckCXXSourceCompiles )
1152+ foreach (_gst_target IN ITEMS GStreamer::GStreamer GStreamerMobile)
1153+ if (TARGET ${_gst_target} )
1154+ set (CMAKE_REQUIRED_LIBRARIES_BACKUP "${CMAKE_REQUIRED_LIBRARIES} " )
1155+ set (CMAKE_REQUIRED_LIBRARIES ${_gst_target} )
1156+ check_cxx_source_compiles ("
1157+ #include <gst/video/gstvideometa.h>
1158+ int main() { GstVideoOrientationMeta *m = nullptr; (void)m; return 0; }
1159+ " QGC_GST_HAS_VIDEO_ORIENTATION_META_${_gst_target} )
1160+ set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_BACKUP} " )
1161+ if (QGC_GST_HAS_VIDEO_ORIENTATION_META_${_gst_target} )
1162+ get_target_property (_gst_aliased ${_gst_target} ALIASED_TARGET )
1163+ if (_gst_aliased)
1164+ set (_gst_real ${_gst_aliased} )
1165+ else ()
1166+ set (_gst_real ${_gst_target} )
1167+ endif ()
1168+ target_compile_definitions (${_gst_real} INTERFACE
1169+ QGC_HAS_GST_VIDEO_ORIENTATION_META=1 )
1170+ endif ()
1171+ endif ()
1172+ endforeach ()
1173+
1174+ # Zero-copy DMABuf GPU path (Linux only). Requires gst-allocators and Qt's
1175+ # private QHwVideoBuffer header. Both are detected here and the combined
1176+ # QGC_HAS_GST_DMABUF_GPU_PATH define is exposed to consumers via
1177+ # target_compile_definitions on the QGCGStreamerDmaBufFeature interface target
1178+ # below — the feature consumer picks it up by linking that target.
1179+ if (LINUX )
1180+ foreach (_gst_target IN ITEMS GStreamer::GStreamer GStreamerMobile)
1181+ if (TARGET ${_gst_target} )
1182+ set (CMAKE_REQUIRED_LIBRARIES_BACKUP "${CMAKE_REQUIRED_LIBRARIES} " )
1183+ set (CMAKE_REQUIRED_LIBRARIES ${_gst_target} )
1184+ check_cxx_source_compiles ("
1185+ #include <gst/allocators/gstdmabuf.h>
1186+ int main() { (void)gst_is_dmabuf_memory; return 0; }
1187+ " QGC_GST_HAS_DMABUF_${_gst_target} )
1188+ set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_BACKUP} " )
1189+ if (QGC_GST_HAS_DMABUF_${_gst_target} )
1190+ set (QGC_GST_HAS_DMABUF TRUE )
1191+ endif ()
1192+ endif ()
1193+ endforeach ()
1194+ endif ()
1195+
11091196include (FindPackageHandleStandardArgs )
11101197find_package_handle_standard_args (QGCGStreamer
11111198 REQUIRED_VARS GStreamer_ROOT_DIR GSTREAMER_LIB_PATH GSTREAMER_PLUGIN_PATH
0 commit comments