CMakeLists.txt 8.4 KB

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