summaryrefslogtreecommitdiffstats
path: root/cmake/FindFFmpeg.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/FindFFmpeg.cmake')
-rw-r--r--cmake/FindFFmpeg.cmake289
1 files changed, 185 insertions, 104 deletions
diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake
index 1ee312578..ecf9b07cb 100644
--- a/cmake/FindFFmpeg.cmake
+++ b/cmake/FindFFmpeg.cmake
@@ -1,3 +1,5 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#.rst:
# FindFFmpeg
# ----------
@@ -18,10 +20,7 @@
# ::
#
# 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.
+# FFMPEG_SHARED_LIBRARIES - Found FFmpeg shared libraries.
#
# For each of the components it will additionally set.
#
@@ -59,8 +58,6 @@
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
# Copyright (c) 2017, Alexander Drozdov, <adrozdoff@gmail.com>
#
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(FindPackageHandleStandardArgs)
@@ -69,14 +66,42 @@ 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 *_LIBRARIES AND *_INCLUDE_DIRS is present.
+# Marks the given component as found if both *_LIBRARY_NAME AND *_INCLUDE_DIRS is present.
#
-macro(set_component_found _component )
- if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
- # message(STATUS " - ${_component} found.")
+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 ()
@@ -114,7 +139,12 @@ macro(find_component _component _pkgconfig _library _header)
list(APPEND CMAKE_FIND_ROOT_PATH "${FFMPEG_ROOT}")
endif()
- find_path(${_component}_INCLUDE_DIRS ${_header}
+ 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}
@@ -125,7 +155,17 @@ macro(find_component _component _pkgconfig _library _header)
ffmpeg include
)
- find_library(${_component}_LIBRARY NAMES ${PC_${_component}_LIBRARIES} ${_library}
+ 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}
@@ -133,140 +173,185 @@ macro(find_component _component _pkgconfig _library _header)
PATHS
${FFMPEG_DIR}
PATH_SUFFIXES
- lib
+ lib bin
)
if(FFMPEG_DIR OR FFMPEG_ROOT)
set(CMAKE_FIND_ROOT_PATH "${__find_ffmpeg_backup_root_dir}")
endif()
- get_filename_component(${_component}_LIBRARY_DIR_FROM_FIND ${${_component}_LIBRARY} DIRECTORY)
- get_filename_component(${_component}_LIBRARY_FROM_FIND ${${_component}_LIBRARY} NAME)
-
- set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
- set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.")
- set(${_component}_LIBRARY_DIRS ${${_component}_LIBRARY_DIR_FROM_FIND} CACHE STRING "The ${_component} library dirs.")
- set(${_component}_LIBRARIES ${${_component}_LIBRARY_FROM_FIND} CACHE STRING "The ${_component} libraries.")
+ if (${_component}_LIBRARY)
+ get_filename_component(${_component}_LIBRARY_DIR ${${_component}_LIBRARY} DIRECTORY)
+ get_filename_component(${_component}_LIBRARY_NAME ${${_component}_LIBRARY} NAME)
-# message("Libs" ${FFMPEG_DIR} ${${_component}_LIBRARIES} ${${_component}_LIBRARY_DIRS})
+ # 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()
-# message(STATUS "L0: ${${_component}_LIBRARIES}")
-# message(STATUS "L1: ${PC_${_component}_LIBRARIES}")
-# message(STATUS "L2: ${_library}")
-# message(STATUS "L3: ${${_component}_LIBRARY}")
-# message(STATUS "L4: ${${_component}_LIBRARY_DIRS}")
+ endif()
+ set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER})
set_component_found(${_component})
- mark_as_advanced(
- ${_component}_LIBRARY
- ${_component}_INCLUDE_DIRS
- ${_component}_LIBRARY_DIRS
- ${_component}_LIBRARIES
- ${_component}_DEFINITIONS
- ${_component}_VERSION)
+ mark_as_advanced(${_component}_LIBRARY)
endmacro()
# Clear the previously cached variables, because they are recomputed every time
# the Find script is included.
-set(FFMPEG_INCLUDE_DIRS "")
-set(FFMPEG_LIBRARIES "")
-set(FFMPEG_DEFINITIONS "")
-set(FFMPEG_LIBRARY_DIRS "")
+unset(FFMPEG_SHARED_LIBRARIES CACHE)
+unset(FFMPEG_STUBS CACHE)
+
+# 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()
+
+
+function(qt_internal_multimedia_try_add_dynamic_resolve_dependency _component dep)
+ set(dynamic_resolve_added FALSE PARENT_SCOPE)
+
+ if (NOT ANDROID AND NOT LINUX)
+ return()
+ endif()
+
+ set(supported_stubs "ssl|crypto|va|va-drm|va-x11")
+ if(${_component}_SHARED_LIBRARIES)
+ set(stub_prefix "Qt${PROJECT_VERSION_MAJOR}FFmpegStub-")
+ if (${dep} MATCHES "^${stub_prefix}(${supported_stubs})$")
+ string(REPLACE "${stub_prefix}" "" dep "${dep}")
+ set(FFMPEG_STUBS ${FFMPEG_STUBS} ${dep} CACHE INTERNAL "")
+
+ set(dynamic_resolve_added TRUE PARENT_SCOPE)
+ endif()
+ elseif (${dep} MATCHES "^(${supported_stubs})$")
+ set(FFMPEG_STUBS ${FFMPEG_STUBS} ${dep} CACHE INTERNAL "")
+ set(dynamic_resolve_added TRUE 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)
+function(__ffmpeg_internal_set_dependencies _component)
+ string(TOLOWER ${_component} lib)
+ set(PC_FILE ${${_component}_LIBRARY_DIR}/pkgconfig/lib${lib}.pc)
if(EXISTS ${PC_FILE})
file(READ ${PC_FILE} pcfile)
- string(REGEX REPLACE ".*Libs:([A-Za-z0-9_. \${}-]+).*" "\\1" out "${pcfile}")
- string(REGEX MATCHALL "\\-l[a-z0-9_-]+" libs_dependency ${out})
- string(REGEX MATCHALL "[A-Za-z0-9_-]+\\.lib" libs_dependency_lib ${out})
-
- string(REGEX REPLACE ".*Libs.private:([A-Za-z0-9_. \${}-]+).*" "\\1" out "${pcfile}")
- string(REGEX MATCHALL "\\-l[a-z0-9_-]+" libs_private_dependency ${out})
- string(REGEX MATCHALL "[A-Za-z0-9_-]+\\.lib" libs_private_dependency_lib ${out})
-
- list(APPEND no_sufix ${libs_dependency} ${libs_private_dependency})
- list(APPEND lib_sufix ${libs_dependency_lib} ${libs_private_dependency_lib})
-
- foreach(d ${no_sufix})
- string(REGEX REPLACE "\\-l" "" d ${d})
- if(NOT ${lib} MATCHES ${d})
- target_link_libraries(FFmpeg::${lib} INTERFACE ${d})
+ 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})
+ qt_internal_multimedia_try_add_dynamic_resolve_dependency(${_component} ${dependency})
+ if(NOT dynamic_resolve_added AND NOT ${_component}_SHARED_LIBRARIES)
+ target_link_libraries(FFmpeg::${lib} INTERFACE ${dependency})
+ endif()
endif()
endforeach()
- foreach(d ${lib_sufix})
- string(REGEX REPLACE "\\.lib" "" d ${d})
- target_link_libraries(FFmpeg::${lib} INTERFACE ${d})
- endforeach()
+
+ if(NOT ${_component}_SHARED_LIBRARIES)
+ 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()
+ else()
+ message(WARNING "FFmpeg pc file ${PC_FILE} is not found")
endif()
endfunction()
# Check for cached results. If there are skip the costly part.
#if (NOT FFMPEG_LIBRARIES)
- # Check for all possible component.
- find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
- find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
- find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
- find_component(AVUTIL libavutil avutil libavutil/avutil.h)
- find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h)
- find_component(SWSCALE libswscale swscale libswscale/swscale.h)
- find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
- find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
-
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
- foreach (_component ${FFmpeg_FIND_COMPONENTS})
- if (${_component}_FOUND)
- # message(STATUS "Libs: ${${_component}_LIBRARIES} | ${PC_${_component}_LIBRARIES}")
-
- # message(STATUS "Required component ${_component} present.")
- set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARY} ${${_component}_LIBRARIES})
- set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
- list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
- list(APPEND FFMPEG_LIBRARY_DIRS ${${_component}_LIBRARY_DIRS})
+ 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_DIRS}
- INTERFACE_LINK_LIBRARIES "${${_component}_LIBRARIES}"
- INTERFACE_LINK_DIRECTORIES "${${_component}_LIBRARY_DIRS}"
+ INTERFACE_INCLUDE_DIRECTORIES ${${_component}_INCLUDE_DIR}
+ INTERFACE_LINK_LIBRARIES "${${_component}_LIBRARY_NAME}"
+ INTERFACE_LINK_DIRECTORIES "${${_component}_LIBRARY_DIR}"
)
- __ffmpeg_internal_set_dependencies(${_lowerComponent})
- target_link_libraries(FFmpeg::${_lowerComponent} INTERFACE "${${_component}_LIBRARY}")
+
+ __ffmpeg_internal_set_dependencies(${_component})
+ 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()
- else()
- # message(STATUS "Required component ${_component} missing.")
+ endif()
endif()
endforeach ()
# Build the include path with duplicates removed.
- if (FFMPEG_INCLUDE_DIRS)
- list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
- endif ()
+ list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
+ list(REMOVE_DUPLICATES FFMPEG_LIBRARY_DIRS)
+ list(REMOVE_DUPLICATES FFMPEG_SHARED_LIBRARIES)
+ list(REMOVE_DUPLICATES FFMPEG_STUBS)
+
+ message(STATUS "FFmpeg shared libs: ${FFMPEG_SHARED_LIBRARIES}")
+ message(STATUS "FFmpeg stubs: ${FFMPEG_STUBS}")
# 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)
+ set(FFMPEG_STUBS ${FFMPEG_STUBS} CACHE STRING "The FFmpeg stubs." FORCE)
- mark_as_advanced(FFMPEG_INCLUDE_DIRS
- FFMPEG_LIBRARIES
- FFMPEG_DEFINITIONS
- FFMPEG_LIBRARY_DIRS)
+ mark_as_advanced(FFMPEG_SHARED_LIBRARIES)
+ mark_as_advanced(FFMPEG_STUBS)
+# endif ()
-#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)
@@ -274,19 +359,15 @@ if (NOT TARGET FFmpeg::FFmpeg)
INTERFACE_COMPILE_OPTIONS "${FFMPEG_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FFMPEG_LIBRARIES}"
- INTERFACE_LINK_DIRECTORIES "${FFMPEG_LIBRARY_DIRS}")
+ INTERFACE_LINK_DIRECTORIES "${FFMPEG_LIBRARY_DIRS}"
+ )
add_library(FFmpeg::FFmpeg ALIAS FFmpeg)
endif()
-# Now set the noncached _FOUND vars for the components.
-foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE)
- set_component_found(${_component})
-endforeach ()
-
# 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}_LIBRARIES ${_component}_INCLUDE_DIRS)
+ list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARY ${_component}_INCLUDE_DIR)
endforeach ()
# Give a nice error message if some of the required vars are missing.