FindFFmpeg.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #[=======================================================================[.rst
  2. FindFFmpeg
  3. ----------
  4. FindModule for FFmpeg and associated libraries
  5. .. versionchanged:: 3.0
  6. Updated FindModule to CMake standards
  7. Components
  8. ^^^^^^^^^^
  9. .. versionadded:: 1.0
  10. This module contains provides several components:
  11. ``avcodec``
  12. ``avdevice``
  13. ``avfilter``
  14. ``avformat``
  15. ``avutil``
  16. ``postproc``
  17. ``swscale``
  18. ``swresample``
  19. Import targets exist for each component.
  20. Imported Targets
  21. ^^^^^^^^^^^^^^^^
  22. .. versionadded:: 2.0
  23. This module defines the :prop_tgt:`IMPORTED` targets:
  24. ``FFmpeg::avcodec``
  25. AVcodec component
  26. ``FFmpeg::avdevice``
  27. AVdevice component
  28. ``FFmpeg::avfilter``
  29. AVfilter component
  30. ``FFmpeg::avformat``
  31. AVformat component
  32. ``FFmpeg::avutil``
  33. AVutil component
  34. ``FFmpeg::postproc``
  35. postproc component
  36. ``FFmpeg::swscale``
  37. SWscale component
  38. ``FFmpeg::swresample``
  39. SWresample component
  40. Result Variables
  41. ^^^^^^^^^^^^^^^^
  42. This module sets the following variables:
  43. ``FFmpeg_FOUND``
  44. True, if all required components and the core library were found.
  45. ``FFmpeg_VERSION``
  46. Detected version of found FFmpeg libraries.
  47. ``FFmpeg_INCLUDE_DIRS``
  48. Include directories needed for FFmpeg.
  49. ``FFmpeg_LIBRARIES``
  50. Libraries needed to link to FFmpeg.
  51. ``FFmpeg_DEFINITIONS``
  52. Compiler flags required for FFmpeg.
  53. ``FFmpeg_<COMPONENT>_VERSION``
  54. Detected version of found FFmpeg component library.
  55. ``FFmpeg_<COMPONENT>_INCLUDE_DIRS``
  56. Include directories needed for FFmpeg component.
  57. ``FFmpeg_<COMPONENT>_LIBRARIES``
  58. Libraries needed to link to FFmpeg component.
  59. ``FFmpeg_<COMPONENT>_DEFINITIONS``
  60. Compiler flags required for FFmpeg component.
  61. Cache variables
  62. ^^^^^^^^^^^^^^^
  63. The following cache variables may also be set:
  64. ``FFmpeg_<COMPONENT>_LIBRARY``
  65. Path to the library component of FFmpeg.
  66. ``FFmpeg_<COMPONENT>_INCLUDE_DIR``
  67. Directory containing ``<COMPONENT>.h``.
  68. #]=======================================================================]
  69. include(FindPackageHandleStandardArgs)
  70. set(
  71. _DEFAULT_COMPONENTS
  72. avcodec
  73. avdevice
  74. avformat
  75. avfilter
  76. avresample
  77. avutil
  78. postproc
  79. swscale
  80. swresample
  81. )
  82. set(component_avcodec libavcodec avcodec avcodec.h)
  83. set(component_avdevice libavdevice avdevice avdevice.h)
  84. set(component_avformat libavformat avformat avformat.h)
  85. set(component_avfilter libavfilter avfilter avfilter.h)
  86. set(component_avresample libavresample avresample avresample.h)
  87. set(component_avutil libavutil avutil avutil.h)
  88. set(component_postproc libpostproc postproc postprocess.h)
  89. set(component_swscale libswscale swscale swscale.h)
  90. set(component_swresample libswresample swresample swresample.h)
  91. if(NOT FFmpeg_FIND_COMPONENTS)
  92. set(FFmpeg_FIND_COMPONENTS ${_DEFAULT_COMPONENTS})
  93. endif()
  94. # FFmpeg_find_component: Find and set up requested FFmpeg component
  95. macro(FFmpeg_find_component component)
  96. list(GET component_${component} 0 component_libname)
  97. list(GET component_${component} 1 component_name)
  98. list(GET component_${component} 2 component_header)
  99. if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
  100. find_package(PkgConfig QUIET)
  101. if(PKG_CONFIG_FOUND)
  102. pkg_search_module(PC_FFmpeg_${component} QUIET ${component_libname})
  103. endif()
  104. endif()
  105. find_path(
  106. FFmpeg_${component}_INCLUDE_DIR
  107. NAMES ${component_libname}/${component_header} ${component_libname}/version.h
  108. HINTS ${PC_FFmpeg_${component}_INCLUDE_DIRS}
  109. PATHS /usr/include /usr/local/include
  110. DOC "FFmpeg component ${component_name} include directory"
  111. )
  112. ffmpeg_check_version()
  113. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
  114. find_library(
  115. FFmpeg_${component}_IMPLIB
  116. NAMES ${component_libname} ${component_name}
  117. DOC "FFmpeg component ${component_name} import library location"
  118. )
  119. ffmpeg_find_dll()
  120. else()
  121. find_library(
  122. FFmpeg_${component}_LIBRARY
  123. NAMES ${component_libname} ${component_name}
  124. HINTS ${PC_FFmpeg_${component}_LIBRARY_DIRS}
  125. PATHS /usr/lib /usr/local/lib
  126. DOC "FFmpeg component ${component_name} location"
  127. )
  128. endif()
  129. if(FFmpeg_${component}_LIBRARY AND FFmpeg_${component}_INCLUDE_DIR)
  130. set(FFmpeg_${component}_FOUND TRUE)
  131. set(FFmpeg_${component}_LIBRARIES ${${_library_var}})
  132. set(FFmpeg_${component}_INCLUDE_DIRS ${FFmpeg_${component}_INCLUDE_DIR})
  133. set(FFmpeg_${component}_DEFINITIONS ${PC_FFmpeg_${component}_CFLAGS_OTHER})
  134. mark_as_advanced(FFmpeg_${component}_LIBRARY FFmpeg_${component}_INCLUDE_DIR FFmpeg_${component}_IMPLIB)
  135. endif()
  136. endmacro()
  137. # FFmpeg_find_dll: Macro to find DLL for corresponding import library
  138. macro(FFmpeg_find_dll)
  139. cmake_path(GET FFmpeg_${component}_IMPLIB PARENT_PATH _implib_path)
  140. cmake_path(SET _bin_path NORMALIZE "${_implib_path}/../bin")
  141. string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" _dll_version "${FFmpeg_${component}_VERSION}")
  142. find_program(
  143. FFmpeg_${component}_LIBRARY
  144. NAMES ${component_name}-${_dll_version}.dll
  145. HINTS ${_implib_path} ${_bin_path}
  146. DOC "FFmpeg component ${component_name} DLL location"
  147. )
  148. if(NOT FFmpeg_${component}_LIBRARY)
  149. set(FFmpeg_${component}_LIBRARY "${FFmpeg_${component}_IMPLIB}")
  150. endif()
  151. unset(_implib_path)
  152. unset(_bin_path)
  153. unset(_dll_version)
  154. endmacro()
  155. # FFmpeg_check_version: Macro to help extract version number from FFmpeg headers
  156. macro(FFmpeg_check_version)
  157. if(PC_FFmpeg_${component}_VERSION)
  158. set(FFmpeg_${component}_VERSION ${PC_FFmpeg_${component}_VERSION})
  159. elseif(EXISTS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h")
  160. if(EXISTS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version_major.h")
  161. file(
  162. STRINGS
  163. "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version_major.h"
  164. _version_string
  165. REGEX "^.*VERSION_MAJOR[ \t]+[0-9]+[ \t]*$"
  166. )
  167. string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _version_major "${_version_string}")
  168. file(
  169. STRINGS
  170. "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h"
  171. _version_string
  172. REGEX "^.*VERSION_(MINOR|MICRO)[ \t]+[0-9]+[ \t]*$"
  173. )
  174. string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _version_minor "${_version_string}")
  175. string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" _version_patch "${_version_string}")
  176. else()
  177. file(
  178. STRINGS
  179. "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h"
  180. _version_string
  181. REGEX "^.*VERSION_(MAJOR|MINOR|MICRO)[ \t]+[0-9]+[ \t]*$"
  182. )
  183. string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _version_major "${_version_string}")
  184. string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _version_minor "${_version_string}")
  185. string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" _version_patch "${_version_string}")
  186. endif()
  187. set(FFmpeg_${component}_VERSION "${_version_major}.${_version_minor}.${_version_patch}")
  188. unset(_version_major)
  189. unset(_version_minor)
  190. unset(_version_patch)
  191. else()
  192. if(NOT FFmpeg_FIND_QUIETLY)
  193. message(AUTHOR_WARNING "Failed to find ${component_name} version.")
  194. endif()
  195. set(FFmpeg_${component}_VERSION 0.0.0)
  196. endif()
  197. endmacro()
  198. # FFmpeg_set_soname: Set SONAME property on imported library targets
  199. macro(FFmpeg_set_soname)
  200. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
  201. execute_process(
  202. COMMAND sh -c "otool -D '${FFmpeg_${component}_LIBRARY}' | grep -v '${FFmpeg_${component}_LIBRARY}'"
  203. OUTPUT_VARIABLE _output
  204. RESULT_VARIABLE _result
  205. )
  206. if(_result EQUAL 0 AND _output MATCHES "^@rpath/")
  207. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_SONAME "${_output}")
  208. endif()
  209. elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|FreeBSD")
  210. execute_process(
  211. COMMAND sh -c "objdump -p '${FFmpeg_${component}_LIBRARY}' | grep SONAME"
  212. OUTPUT_VARIABLE _output
  213. RESULT_VARIABLE _result
  214. )
  215. if(_result EQUAL 0)
  216. string(REGEX REPLACE "[ \t]+SONAME[ \t]+([^ \t]+)" "\\1" _soname "${_output}")
  217. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_SONAME "${_soname}")
  218. unset(_soname)
  219. endif()
  220. endif()
  221. unset(_output)
  222. unset(_result)
  223. endmacro()
  224. foreach(component IN LISTS FFmpeg_FIND_COMPONENTS)
  225. if(NOT component IN_LIST _DEFAULT_COMPONENTS)
  226. message(FATAL_ERROR "Unknown FFmpeg component specified: ${component}.")
  227. endif()
  228. if(NOT FFmpeg_${component}_FOUND)
  229. ffmpeg_find_component(${component})
  230. endif()
  231. if(FFmpeg_${component}_FOUND)
  232. list(APPEND FFmpeg_LIBRARIES ${FFmpeg_${component}_LIBRARY})
  233. list(APPEND FFmpeg_DEFINITIONS ${FFmpeg_${component}_DEFINITIONS})
  234. list(APPEND FFmpeg_INCLUDE_DIRS ${FFmpeg_${component}_INCLUDE_DIR})
  235. endif()
  236. endforeach()
  237. if(NOT FFmpeg_avutil_FOUND)
  238. ffmpeg_find_component(avutil)
  239. endif()
  240. if(EXISTS "${FFmpeg_avutil_INCLUDE_DIR}/libavutil/ffversion.h")
  241. file(
  242. STRINGS
  243. "${FFmpeg_avutil_INCLUDE_DIR}/libavutil/ffversion.h"
  244. _version_string
  245. REGEX "^.*FFMPEG_VERSION[ \t]+\"n?[0-9a-z\\~+.-]+\"[ \t]*$"
  246. )
  247. string(REGEX REPLACE ".*FFMPEG_VERSION[ \t]+\"n?([0-9]+\\.[0-9]).*\".*" "\\1" FFmpeg_VERSION "${_version_string}")
  248. endif()
  249. list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIRS)
  250. list(REMOVE_DUPLICATES FFmpeg_LIBRARIES)
  251. list(REMOVE_DUPLICATES FFmpeg_DEFINITIONS)
  252. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin|Windows")
  253. set(FFmpeg_ERROR_REASON "Ensure that obs-deps is provided as part of CMAKE_PREFIX_PATH.")
  254. elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|FreeBSD")
  255. set(FFmpeg_ERROR_REASON "Ensure that required FFmpeg libraries are installed on the system.")
  256. endif()
  257. find_package_handle_standard_args(
  258. FFmpeg
  259. REQUIRED_VARS FFmpeg_LIBRARIES FFmpeg_INCLUDE_DIRS
  260. VERSION_VAR FFmpeg_VERSION
  261. HANDLE_COMPONENTS
  262. REASON_FAILURE_MESSAGE "${FFmpeg_ERROR_REASON}"
  263. )
  264. if(FFmpeg_FOUND AND NOT TARGET FFmpeg::FFmpeg)
  265. add_library(FFmpeg::FFmpeg INTERFACE IMPORTED)
  266. endif()
  267. foreach(component IN LISTS FFmpeg_FIND_COMPONENTS)
  268. if(FFmpeg_${component}_FOUND AND NOT TARGET FFmpeg::${component})
  269. if(IS_ABSOLUTE "${FFmpeg_${component}_LIBRARY}")
  270. if(DEFINED FFmpeg_${component}_IMPLIB)
  271. if(FFmpeg_${component}_IMPLIB STREQUAL FFmpeg_${component}_LIBRARY)
  272. add_library(FFmpeg::${component} STATIC IMPORTED)
  273. else()
  274. add_library(FFmpeg::${component} SHARED IMPORTED)
  275. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_IMPLIB "${FFmpeg_${component}_IMPLIB}")
  276. endif()
  277. else()
  278. add_library(FFmpeg::${component} UNKNOWN IMPORTED)
  279. ffmpeg_set_soname()
  280. endif()
  281. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_LOCATION "${FFmpeg_${component}_LIBRARY}")
  282. else()
  283. add_library(FFmpeg::${component} INTERFACE IMPORTED)
  284. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_LIBNAME "${FFmpeg_${component}_LIBRARY}")
  285. endif()
  286. set_target_properties(
  287. FFmpeg::${component}
  288. PROPERTIES
  289. INTERFACE_COMPILE_OPTIONS "${PC_FFmpeg_${component}_CFLAGS_OTHER}"
  290. INTERFACE_INCLUDE_DIRECTORIES "${FFmpeg_${component}_INCLUDE_DIR}"
  291. VERSION ${FFmpeg_${component}_VERSION}
  292. )
  293. get_target_property(_ffmpeg_interface_libraries FFmpeg::FFmpeg INTERFACE_LINK_LIBRARIES)
  294. if(NOT FFmpeg::${component} IN_LIST _ffmpeg_interface_libraries)
  295. set_property(TARGET FFmpeg::FFmpeg APPEND PROPERTY INTERFACE_LINK_LIBRARIES FFmpeg::${component})
  296. endif()
  297. endif()
  298. endforeach()
  299. include(FeatureSummary)
  300. set_package_properties(
  301. FFmpeg
  302. PROPERTIES
  303. URL "https://www.ffmpeg.org"
  304. DESCRIPTION "A complete, cross-platform solution to record, convert and stream audio and video."
  305. )