CMakeLists.txt 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. # SPDX-FileCopyrightText: 2021 yuzu Emulator Project
  2. # SPDX-License-Identifier: GPL-2.0-or-later
  3. if (NOT WIN32)
  4. # Build FFmpeg from externals
  5. message(STATUS "Using FFmpeg from externals")
  6. if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64)")
  7. # FFmpeg has source that requires one of nasm or yasm to assemble it.
  8. # REQUIRED throws an error if not found here during configuration rather than during compilation.
  9. find_program(ASSEMBLER NAMES nasm yasm)
  10. if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
  11. message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
  12. endif()
  13. endif()
  14. find_program(AUTOCONF autoconf)
  15. if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
  16. message(FATAL_ERROR "Required program `autoconf` not found.")
  17. endif()
  18. set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg/ffmpeg)
  19. set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg-build)
  20. set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
  21. make_directory(${FFmpeg_BUILD_DIR})
  22. # Read version string from external
  23. file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
  24. set(FFmpeg_FOUND NO)
  25. if (NOT FFmpeg_VERSION STREQUAL "")
  26. set(FFmpeg_FOUND YES)
  27. endif()
  28. unset(FFmpeg_LIBRARIES CACHE)
  29. foreach(COMPONENT ${FFmpeg_COMPONENTS})
  30. set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
  31. set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
  32. set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
  33. set(FFmpeg_LIBRARIES
  34. ${FFmpeg_LIBRARIES}
  35. ${FFmpeg_${COMPONENT}_LIBRARY}
  36. CACHE PATH "Paths to FFmpeg libraries" FORCE)
  37. endforeach()
  38. find_package(PkgConfig REQUIRED)
  39. pkg_check_modules(LIBVA libva)
  40. pkg_check_modules(CUDA cuda)
  41. pkg_check_modules(FFNVCODEC ffnvcodec)
  42. pkg_check_modules(VDPAU vdpau)
  43. set(FFmpeg_HWACCEL_LIBRARIES)
  44. set(FFmpeg_HWACCEL_FLAGS)
  45. set(FFmpeg_HWACCEL_INCLUDE_DIRS)
  46. set(FFmpeg_HWACCEL_LDFLAGS)
  47. if(LIBVA_FOUND)
  48. pkg_check_modules(LIBDRM libdrm REQUIRED)
  49. find_package(X11 REQUIRED)
  50. pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
  51. pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
  52. list(APPEND FFmpeg_HWACCEL_LIBRARIES
  53. ${LIBDRM_LIBRARIES}
  54. ${X11_LIBRARIES}
  55. ${LIBVA-DRM_LIBRARIES}
  56. ${LIBVA-X11_LIBRARIES}
  57. ${LIBVA_LIBRARIES})
  58. set(FFmpeg_HWACCEL_FLAGS
  59. --enable-hwaccel=h264_vaapi
  60. --enable-hwaccel=vp8_vaapi
  61. --enable-hwaccel=vp9_vaapi
  62. --enable-libdrm)
  63. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
  64. ${LIBDRM_INCLUDE_DIRS}
  65. ${X11_INCLUDE_DIRS}
  66. ${LIBVA-DRM_INCLUDE_DIRS}
  67. ${LIBVA-X11_INCLUDE_DIRS}
  68. ${LIBVA_INCLUDE_DIRS}
  69. )
  70. message(STATUS "VA-API found")
  71. else()
  72. set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
  73. endif()
  74. if (FFNVCODEC_FOUND)
  75. list(APPEND FFmpeg_HWACCEL_FLAGS
  76. --enable-cuvid
  77. --enable-ffnvcodec
  78. --enable-nvdec
  79. --enable-hwaccel=h264_nvdec
  80. --enable-hwaccel=vp8_nvdec
  81. --enable-hwaccel=vp9_nvdec
  82. )
  83. list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES})
  84. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS})
  85. list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS})
  86. message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
  87. # ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress
  88. # here we handle the hard-linking senario where CUDA is linked during compilation
  89. if (CUDA_FOUND)
  90. # This line causes build error if CUDA_INCLUDE_DIRS is anything but a single non-empty value
  91. #list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
  92. list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
  93. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
  94. list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
  95. message(STATUS "CUDA libraries found, hard-linking will be performed")
  96. endif(CUDA_FOUND)
  97. endif()
  98. if (VDPAU_FOUND)
  99. list(APPEND FFmpeg_HWACCEL_FLAGS
  100. --enable-vdpau
  101. --enable-hwaccel=h264_vdpau
  102. --enable-hwaccel=vp9_vdpau
  103. )
  104. list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
  105. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
  106. list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
  107. message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
  108. else()
  109. list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
  110. endif()
  111. # `configure` parameters builds only exactly what yuzu needs from FFmpeg
  112. # `--disable-vdpau` is needed to avoid linking issues
  113. set(FFmpeg_CC ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER})
  114. set(FFmpeg_CXX ${CMAKE_CXX_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER})
  115. add_custom_command(
  116. OUTPUT
  117. ${FFmpeg_MAKEFILE}
  118. COMMAND
  119. /bin/bash ${FFmpeg_PREFIX}/configure
  120. --disable-avdevice
  121. --disable-avfilter
  122. --disable-avformat
  123. --disable-doc
  124. --disable-everything
  125. --disable-ffmpeg
  126. --disable-ffprobe
  127. --disable-network
  128. --disable-postproc
  129. --disable-swresample
  130. --enable-decoder=h264
  131. --enable-decoder=vp8
  132. --enable-decoder=vp9
  133. --cc="${FFmpeg_CC}"
  134. --cxx="${FFmpeg_CXX}"
  135. ${FFmpeg_HWACCEL_FLAGS}
  136. WORKING_DIRECTORY
  137. ${FFmpeg_BUILD_DIR}
  138. )
  139. unset(FFmpeg_CC)
  140. unset(FFmpeg_CXX)
  141. unset(FFmpeg_HWACCEL_FLAGS)
  142. # Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
  143. # with context of the jobserver. Also helps ninja users.
  144. execute_process(
  145. COMMAND
  146. nproc
  147. OUTPUT_VARIABLE
  148. SYSTEM_THREADS)
  149. set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
  150. add_custom_command(
  151. OUTPUT
  152. ${FFmpeg_BUILD_LIBRARIES}
  153. COMMAND
  154. make -j${SYSTEM_THREADS}
  155. WORKING_DIRECTORY
  156. ${FFmpeg_BUILD_DIR}
  157. )
  158. set(FFmpeg_INCLUDE_DIR
  159. "${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
  160. CACHE PATH "Path to FFmpeg headers" FORCE)
  161. set(FFmpeg_LDFLAGS
  162. "${FFmpeg_HWACCEL_LDFLAGS}"
  163. CACHE STRING "FFmpeg linker flags" FORCE)
  164. # ALL makes this custom target build every time
  165. # but it won't actually build if the DEPENDS parameter is up to date
  166. add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
  167. add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
  168. link_libraries(${FFmpeg_LIBVA_LIBRARIES})
  169. set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
  170. CACHE PATH "Paths to FFmpeg libraries" FORCE)
  171. unset(FFmpeg_BUILD_LIBRARIES)
  172. unset(FFmpeg_HWACCEL_FLAGS)
  173. unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
  174. unset(FFmpeg_HWACCEL_LDFLAGS)
  175. unset(FFmpeg_HWACCEL_LIBRARIES)
  176. if (FFmpeg_FOUND)
  177. message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
  178. else()
  179. message(FATAL_ERROR "FFmpeg not found")
  180. endif()
  181. else(WIN32)
  182. # Use yuzu FFmpeg binaries
  183. set(FFmpeg_EXT_NAME "ffmpeg-4.4")
  184. set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
  185. download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
  186. set(FFmpeg_FOUND YES)
  187. set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
  188. set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
  189. set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
  190. set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
  191. set(FFmpeg_LIBRARIES
  192. ${FFmpeg_LIBRARY_DIR}/swscale.lib
  193. ${FFmpeg_LIBRARY_DIR}/avcodec.lib
  194. ${FFmpeg_LIBRARY_DIR}/avutil.lib
  195. CACHE PATH "Paths to FFmpeg libraries" FORCE)
  196. # exported variables
  197. set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
  198. set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
  199. set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
  200. set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
  201. endif()
  202. unset(FFmpeg_COMPONENTS)