CMakeLists.txt 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
  89. list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
  90. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
  91. list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
  92. message(STATUS "CUDA libraries found, hard-linking will be performed")
  93. endif(CUDA_FOUND)
  94. endif()
  95. if (VDPAU_FOUND)
  96. list(APPEND FFmpeg_HWACCEL_FLAGS
  97. --enable-vdpau
  98. --enable-hwaccel=h264_vdpau
  99. --enable-hwaccel=vp9_vdpau
  100. )
  101. list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
  102. list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
  103. list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
  104. message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
  105. else()
  106. list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
  107. endif()
  108. # `configure` parameters builds only exactly what yuzu needs from FFmpeg
  109. # `--disable-vdpau` is needed to avoid linking issues
  110. add_custom_command(
  111. OUTPUT
  112. ${FFmpeg_MAKEFILE}
  113. COMMAND
  114. /bin/bash ${FFmpeg_PREFIX}/configure
  115. --disable-avdevice
  116. --disable-avfilter
  117. --disable-avformat
  118. --disable-doc
  119. --disable-everything
  120. --disable-ffmpeg
  121. --disable-ffprobe
  122. --disable-network
  123. --disable-postproc
  124. --disable-swresample
  125. --enable-decoder=h264
  126. --enable-decoder=vp8
  127. --enable-decoder=vp9
  128. --cc="${CMAKE_C_COMPILER}"
  129. --cxx="${CMAKE_CXX_COMPILER}"
  130. ${FFmpeg_HWACCEL_FLAGS}
  131. WORKING_DIRECTORY
  132. ${FFmpeg_BUILD_DIR}
  133. )
  134. unset(FFmpeg_HWACCEL_FLAGS)
  135. # Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
  136. # with context of the jobserver. Also helps ninja users.
  137. execute_process(
  138. COMMAND
  139. nproc
  140. OUTPUT_VARIABLE
  141. SYSTEM_THREADS)
  142. set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
  143. add_custom_command(
  144. OUTPUT
  145. ${FFmpeg_BUILD_LIBRARIES}
  146. COMMAND
  147. make -j${SYSTEM_THREADS}
  148. WORKING_DIRECTORY
  149. ${FFmpeg_BUILD_DIR}
  150. )
  151. set(FFmpeg_INCLUDE_DIR
  152. "${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
  153. CACHE PATH "Path to FFmpeg headers" FORCE)
  154. set(FFmpeg_LDFLAGS
  155. "${FFmpeg_HWACCEL_LDFLAGS}"
  156. CACHE STRING "FFmpeg linker flags" FORCE)
  157. # ALL makes this custom target build every time
  158. # but it won't actually build if the DEPENDS parameter is up to date
  159. add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
  160. add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
  161. link_libraries(${FFmpeg_LIBVA_LIBRARIES})
  162. set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
  163. CACHE PATH "Paths to FFmpeg libraries" FORCE)
  164. unset(FFmpeg_BUILD_LIBRARIES)
  165. unset(FFmpeg_HWACCEL_FLAGS)
  166. unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
  167. unset(FFmpeg_HWACCEL_LDFLAGS)
  168. unset(FFmpeg_HWACCEL_LIBRARIES)
  169. if (FFmpeg_FOUND)
  170. message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
  171. else()
  172. message(FATAL_ERROR "FFmpeg not found")
  173. endif()
  174. else(WIN32)
  175. # Use yuzu FFmpeg binaries
  176. set(FFmpeg_EXT_NAME "ffmpeg-4.4")
  177. set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
  178. download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
  179. set(FFmpeg_FOUND YES)
  180. set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
  181. set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
  182. set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
  183. set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
  184. set(FFmpeg_LIBRARIES
  185. ${FFmpeg_LIBRARY_DIR}/swscale.lib
  186. ${FFmpeg_LIBRARY_DIR}/avcodec.lib
  187. ${FFmpeg_LIBRARY_DIR}/avutil.lib
  188. CACHE PATH "Paths to FFmpeg libraries" FORCE)
  189. # exported variables
  190. set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
  191. set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
  192. set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
  193. set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
  194. endif(WIN32)
  195. unset(FFmpeg_COMPONENTS)