From 82dd376ba26df744340f947148e073bf250207bd Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:41:45 -0500 Subject: [PATCH 1/9] externals: Add submodule ffmpeg --- .gitmodules | 3 +++ externals/ffmpeg | 1 + 2 files changed, 4 insertions(+) create mode 160000 externals/ffmpeg diff --git a/.gitmodules b/.gitmodules index 41022615b..4962f7bfd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "opus"] path = externals/opus/opus url = https://github.com/xiph/opus.git +[submodule "externals/ffmpeg"] + path = externals/ffmpeg + url = https://git.ffmpeg.org/ffmpeg.git diff --git a/externals/ffmpeg b/externals/ffmpeg new file mode 160000 index 000000000..81c462ad9 --- /dev/null +++ b/externals/ffmpeg @@ -0,0 +1 @@ +Subproject commit 81c462ad95f143837a6a21126117515577f0977b From 47401016bfbcd904edd22a4a1bf772e893ad36f6 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:45:10 -0500 Subject: [PATCH 2/9] CMake: Implement YUZU_USE_BUNDLED_FFMPEG For Linux, instructs CMake to use the FFmpeg submodule in externals. This is HEAVILY based on our usage of the late Unicorn. Minimal change to MSVC as it uses the yuzu-emu/ext-windows-bin. MinGW now targets the same ext-windows-bin libraries as MSVC for FFmpeg. Adds FFMPEG_LIBRARIES to WIN32 and simplifies video_core/CMakeLists.txt a bit. --- CMakeLists.txt | 112 ++++++++++++++++-- src/video_core/CMakeLists.txt | 11 +- .../command_classes/codecs/codec.cpp | 2 +- 3 files changed, 108 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27aa56780..aafe73c44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "EN option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) +option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled yuzu" ON) + option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON) @@ -384,17 +386,107 @@ if (NOT LIBUSB_FOUND) set(LIBUSB_LIBRARIES usb) endif() -# Use system installed ffmpeg. -if (NOT MSVC) - find_package(FFmpeg REQUIRED) +if (YUZU_USE_BUNDLED_FFMPEG) + if (NOT WIN32) + # Build FFmpeg from externals + message(STATUS "Using FFmpeg from externals") + + set(FFMPEG_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) + set(FFMPEG_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) + set(FFMPEG_MAKEFILE ${FFMPEG_BUILD_DIR}/Makefile) + make_directory(${FFMPEG_BUILD_DIR}) + + # Read version string from external + file(READ ${FFMPEG_PREFIX}/RELEASE FFMPEG_VERSION) + set(FFMPEG_FOUND NO) + if (NOT FFMPEG_VERSION STREQUAL "") + set(FFMPEG_FOUND YES) + endif() + + set(FFMPEG_COMPONENTS + avcodec + avutil + swscale) + + foreach(COMPONENT ${FFMPEG_COMPONENTS}) + set(FFMPEG_${COMPONENT}_PREFIX "${FFMPEG_BUILD_DIR}/lib${COMPONENT}") + set(FFMPEG_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") + set(FFMPEG_${COMPONENT}_LIBRARY "${FFMPEG_${COMPONENT}_PREFIX}/${FFMPEG_${COMPONENT}_LIB_NAME}") + + set(FFMPEG_LIBRARIES + ${FFMPEG_LIBRARIES} + ${FFMPEG_${COMPONENT}_LIBRARY} + CACHE PATH "Paths to FFmpeg libraries" FORCE) + endforeach() + + set(FFMPEG_INCLUDE_DIR + ${FFMPEG_PREFIX} + CACHE PATH "Path to FFmpeg headers" FORCE) + + # `configure` parameters builds only exactly what yuzu needs from FFmpeg + # `--disable-{vaapi,vdpau}` is needed to avoid linking issues + add_custom_command( + OUTPUT + ${FFMPEG_MAKEFILE} + COMMAND + /bin/bash ${FFMPEG_PREFIX}/configure + --disable-avdevice + --disable-avfilter + --disable-avformat + --disable-doc + --disable-everything + --disable-ffmpeg + --disable-ffprobe + --disable-network + --disable-postproc + --disable-swresample + --disable-vaapi + --disable-vdpau + --enable-decoder=h264 + --enable-decoder=vp9 + WORKING_DIRECTORY + ${FFMPEG_BUILD_DIR} + ) + + add_custom_command( + OUTPUT + ${FFMPEG_LIBRARIES} + COMMAND + make + WORKING_DIRECTORY + ${FFMPEG_BUILD_DIR} + ) + + # ALL makes this custom target build every time + # but it won't actually build if the DEPENDS parameter is up to date + add_custom_target(ffmpeg-build ALL DEPENDS ${FFMPEG_LIBRARIES}) + add_custom_target(ffmpeg-configure ALL DEPENDS ${FFMPEG_MAKEFILE}) + + if (FFMPEG_FOUND) + message(STATUS "Found FFmpeg version ${FFMPEG_VERSION}") + + add_dependencies(ffmpeg-build ffmpeg-configure) + else() + message(FATAL_ERROR "FFmpeg not found") + endif() + else() # WIN32 + # Use yuzu FFmpeg binaries + set(FFMPEG_EXT_NAME "ffmpeg-4.2.1") + set(FFMPEG_PATH "${CMAKE_BINARY_DIR}/externals/${FFMPEG_EXT_NAME}") + download_bundled_external("ffmpeg/" ${FFMPEG_EXT_NAME} "") + set(FFMPEG_FOUND YES) + set(FFMPEG_INCLUDE_DIR "${FFMPEG_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) + set(FFMPEG_LIBRARY_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE) + set(FFMPEG_DLL_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) + set(FFMPEG_LIBRARIES + ${FFMPEG_LIBRARY_DIR}/swscale.lib + ${FFMPEG_LIBRARY_DIR}/avcodec.lib + ${FFMPEG_LIBRARY_DIR}/avutil.lib + CACHE PATH "Paths to FFmpeg libraries" FORCE) + endif() else() - set(FFMPEG_EXT_NAME "ffmpeg-4.2.1") - set(FFMPEG_PATH "${CMAKE_BINARY_DIR}/externals/${FFMPEG_EXT_NAME}") - download_bundled_external("ffmpeg/" ${FFMPEG_EXT_NAME} "") - set(FFMPEG_FOUND YES) - set(FFMPEG_INCLUDE_DIR "${FFMPEG_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) - set(FFMPEG_LIBRARY_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg library" FORCE) - set(FFMPEG_DLL_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) + # Use system installed FFmpeg + find_package(FFmpeg REQUIRED VERSION 4.0) endif() # Prefer the -pthread flag on Linux. diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index bb1f8491f..01e284d8c 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -273,14 +273,13 @@ create_target_directory_groups(video_core) target_link_libraries(video_core PUBLIC common core) target_link_libraries(video_core PRIVATE glad xbyak) -if (MSVC) - target_include_directories(video_core PRIVATE ${FFMPEG_INCLUDE_DIR}) - target_link_libraries(video_core PUBLIC ${FFMPEG_LIBRARY_DIR}/swscale.lib ${FFMPEG_LIBRARY_DIR}/avcodec.lib ${FFMPEG_LIBRARY_DIR}/avutil.lib) -else() - target_include_directories(video_core PRIVATE ${FFMPEG_INCLUDE_DIR}) - target_link_libraries(video_core PRIVATE ${FFMPEG_LIBRARIES}) +if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) + add_dependencies(video_core ffmpeg-build) endif() +target_include_directories(video_core PRIVATE ${FFMPEG_INCLUDE_DIR}) +target_link_libraries(video_core PRIVATE ${FFMPEG_LIBRARIES}) + add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index 39bc923a5..c25d2ad2c 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp @@ -13,7 +13,7 @@ #include "video_core/memory_manager.h" extern "C" { -#include +#include "libavutil/opt.h" } namespace Tegra { From 0913aaa42a710b6b9d18119185925912a53295d9 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:51:36 -0500 Subject: [PATCH 3/9] ci/windows: Copy downloaded FFmpeg libraries Copies FFmpeg libraries that were downloaded during the CMake configuration. Fixes dynamic linking issues with the MinGW builds. --- .ci/scripts/windows/docker.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.ci/scripts/windows/docker.sh b/.ci/scripts/windows/docker.sh index 2bc9f36ab..192a01fd8 100755 --- a/.ci/scripts/windows/docker.sh +++ b/.ci/scripts/windows/docker.sh @@ -42,3 +42,8 @@ done pip3 install pefile python3 .ci/scripts/windows/scan_dll.py package/*.exe "package/" python3 .ci/scripts/windows/scan_dll.py package/imageformats/*.dll "package/" + +# copy FFmpeg libraries +EXTERNALS_PATH="$(pwd)/build/externals" +FFMPEG_DLL_PATH="$(find ${EXTERNALS_PATH} -maxdepth 1 -type d | grep ffmpeg)/bin" +find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';' From 1d19eac415199bd4c768f1cbebc9f23298734545 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 15:39:19 -0500 Subject: [PATCH 4/9] CMake: Port citra-emu/citra FindFFmpeg.cmake Also renames related CMake variables to match both the Find*FFmpeg* and variables defined within the file. Fixes odd errors produced by the old FindFFmpeg. Citra's FindFFmpeg is slightly modified here: adds Citra's copyright at the beginning, renames FFmpeg_INCLUDES to FFmpeg_INCLUDE_DIR, disables a few components in _FFmpeg_ALL_COMPONENTS, and adds the missing avutil component to the comment above. --- CMakeLists.txt | 82 ++++---- externals/find-modules/FindFFmpeg.cmake | 256 ++++++++++++++++-------- src/video_core/CMakeLists.txt | 4 +- 3 files changed, 214 insertions(+), 128 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aafe73c44..fc3e93f80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,45 +391,45 @@ if (YUZU_USE_BUNDLED_FFMPEG) # Build FFmpeg from externals message(STATUS "Using FFmpeg from externals") - set(FFMPEG_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) - set(FFMPEG_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) - set(FFMPEG_MAKEFILE ${FFMPEG_BUILD_DIR}/Makefile) - make_directory(${FFMPEG_BUILD_DIR}) + set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) + set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) + set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile) + make_directory(${FFmpeg_BUILD_DIR}) # Read version string from external - file(READ ${FFMPEG_PREFIX}/RELEASE FFMPEG_VERSION) - set(FFMPEG_FOUND NO) - if (NOT FFMPEG_VERSION STREQUAL "") - set(FFMPEG_FOUND YES) + file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION) + set(FFmpeg_FOUND NO) + if (NOT FFmpeg_VERSION STREQUAL "") + set(FFmpeg_FOUND YES) endif() - set(FFMPEG_COMPONENTS + set(FFmpeg_COMPONENTS avcodec avutil swscale) - foreach(COMPONENT ${FFMPEG_COMPONENTS}) - set(FFMPEG_${COMPONENT}_PREFIX "${FFMPEG_BUILD_DIR}/lib${COMPONENT}") - set(FFMPEG_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") - set(FFMPEG_${COMPONENT}_LIBRARY "${FFMPEG_${COMPONENT}_PREFIX}/${FFMPEG_${COMPONENT}_LIB_NAME}") + foreach(COMPONENT ${FFmpeg_COMPONENTS}) + set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}") + set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") + set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}") - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBRARIES} - ${FFMPEG_${COMPONENT}_LIBRARY} + set(FFmpeg_LIBRARIES + ${FFmpeg_LIBRARIES} + ${FFmpeg_${COMPONENT}_LIBRARY} CACHE PATH "Paths to FFmpeg libraries" FORCE) endforeach() - set(FFMPEG_INCLUDE_DIR - ${FFMPEG_PREFIX} + set(FFmpeg_INCLUDE_DIR + ${FFmpeg_PREFIX} CACHE PATH "Path to FFmpeg headers" FORCE) # `configure` parameters builds only exactly what yuzu needs from FFmpeg # `--disable-{vaapi,vdpau}` is needed to avoid linking issues add_custom_command( OUTPUT - ${FFMPEG_MAKEFILE} + ${FFmpeg_MAKEFILE} COMMAND - /bin/bash ${FFMPEG_PREFIX}/configure + /bin/bash ${FFmpeg_PREFIX}/configure --disable-avdevice --disable-avfilter --disable-avformat @@ -445,25 +445,25 @@ if (YUZU_USE_BUNDLED_FFMPEG) --enable-decoder=h264 --enable-decoder=vp9 WORKING_DIRECTORY - ${FFMPEG_BUILD_DIR} + ${FFmpeg_BUILD_DIR} ) add_custom_command( OUTPUT - ${FFMPEG_LIBRARIES} + ${FFmpeg_LIBRARIES} COMMAND make WORKING_DIRECTORY - ${FFMPEG_BUILD_DIR} + ${FFmpeg_BUILD_DIR} ) # ALL makes this custom target build every time # but it won't actually build if the DEPENDS parameter is up to date - add_custom_target(ffmpeg-build ALL DEPENDS ${FFMPEG_LIBRARIES}) - add_custom_target(ffmpeg-configure ALL DEPENDS ${FFMPEG_MAKEFILE}) + add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES}) + add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE}) - if (FFMPEG_FOUND) - message(STATUS "Found FFmpeg version ${FFMPEG_VERSION}") + if (FFmpeg_FOUND) + message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}") add_dependencies(ffmpeg-build ffmpeg-configure) else() @@ -471,22 +471,26 @@ if (YUZU_USE_BUNDLED_FFMPEG) endif() else() # WIN32 # Use yuzu FFmpeg binaries - set(FFMPEG_EXT_NAME "ffmpeg-4.2.1") - set(FFMPEG_PATH "${CMAKE_BINARY_DIR}/externals/${FFMPEG_EXT_NAME}") - download_bundled_external("ffmpeg/" ${FFMPEG_EXT_NAME} "") - set(FFMPEG_FOUND YES) - set(FFMPEG_INCLUDE_DIR "${FFMPEG_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) - set(FFMPEG_LIBRARY_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE) - set(FFMPEG_DLL_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBRARY_DIR}/swscale.lib - ${FFMPEG_LIBRARY_DIR}/avcodec.lib - ${FFMPEG_LIBRARY_DIR}/avutil.lib + set(FFmpeg_EXT_NAME "ffmpeg-4.2.1") + set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}") + download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "") + set(FFmpeg_FOUND YES) + set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) + set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE) + set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) + set(FFmpeg_LIBRARIES + ${FFmpeg_LIBRARY_DIR}/swscale.lib + ${FFmpeg_LIBRARY_DIR}/avcodec.lib + ${FFmpeg_LIBRARY_DIR}/avutil.lib CACHE PATH "Paths to FFmpeg libraries" FORCE) endif() else() # Use system installed FFmpeg - find_package(FFmpeg REQUIRED VERSION 4.0) + find_package(FFmpeg REQUIRED) + + if (NOT FFmpeg_FOUND) + message(FATAL_ERROR "FFmpeg not found") + endif() endif() # Prefer the -pthread flag on Linux. diff --git a/externals/find-modules/FindFFmpeg.cmake b/externals/find-modules/FindFFmpeg.cmake index 77b331e00..86a3f5a5a 100644 --- a/externals/find-modules/FindFFmpeg.cmake +++ b/externals/find-modules/FindFFmpeg.cmake @@ -1,100 +1,182 @@ -# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) -# Once done this will define +# FindFFmpeg +# ---------- # -# FFMPEG_FOUND - system has ffmpeg or libav -# FFMPEG_INCLUDE_DIR - the ffmpeg include directory -# FFMPEG_LIBRARIES - Link these to use ffmpeg -# FFMPEG_LIBAVCODEC -# FFMPEG_LIBAVFORMAT -# FFMPEG_LIBAVUTIL +# Copyright 2019 Citra Emulator Project +# Licensed under GPLv2 or any later version # -# Copyright (c) 2008 Andreas Schneider -# Modified for other libraries by Lasse Kärkkäinen -# Modified for Hedgewars by Stepik777 -# Modified for FFmpeg-example Tuukka Pasanen 2018 -# Modified for yuzu toastUnlimted 2020 +# Find the native FFmpeg includes and libraries # -# Redistribution and use is allowed according to the terms of the New -# BSD license. +# This module defines the following variables: +# +# FFmpeg_INCLUDE_: where to find .h +# FFmpeg_LIBRARY_: where to find the library +# FFmpeg_INCLUDE_DIR: aggregate all the include paths +# FFmpeg_LIBRARIES: aggregate all the paths to the libraries +# FFmpeg_FOUND: True if all components have been found +# +# This module defines the following targets, which are prefered over variables: +# +# FFmpeg::: Target to use directly, with include path, +# library and dependencies set up. If you are using a static build, you are +# responsible for adding any external dependencies (such as zlib, bzlib...). +# +# can be one of: +# avcodec +# avdevice # Disabled +# avfilter # Disabled +# avformat # Disabled +# avutil +# postproc # Disabled +# swresample # Disabled +# swscale # -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(FFMPEG - FOUND_VAR FFMPEG_FOUND - REQUIRED_VARS - FFMPEG_LIBRARY - FFMPEG_INCLUDE_DIR - VERSION_VAR FFMPEG_VERSION +set(_FFmpeg_ALL_COMPONENTS + avcodec + avutil + swscale ) -if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) - # in cache already - set(FFMPEG_FOUND TRUE) -else() - # use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - find_package(PkgConfig) - if(PKG_CONFIG_FOUND) - pkg_check_modules(_FFMPEG_AVCODEC libavcodec) - pkg_check_modules(_FFMPEG_AVUTIL libavutil) - pkg_check_modules(_FFMPEG_SWSCALE libswscale) +set(_FFmpeg_DEPS_avcodec avutil) +set(_FFmpeg_DEPS_avdevice avcodec avformat avutil) +set(_FFmpeg_DEPS_avfilter avutil) +set(_FFmpeg_DEPS_avformat avcodec avutil) +set(_FFmpeg_DEPS_postproc avutil) +set(_FFmpeg_DEPS_swresample avutil) +set(_FFmpeg_DEPS_swscale avutil) + +function(find_ffmpeg LIBNAME) + if(DEFINED ENV{FFMPEG_DIR}) + set(FFMPEG_DIR $ENV{FFMPEG_DIR}) endif() - find_path(FFMPEG_AVCODEC_INCLUDE_DIR - NAMES libavcodec/avcodec.h - PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} - /usr/include - /usr/local/include - /opt/local/include - /sw/include - PATH_SUFFIXES ffmpeg libav) - - find_library(FFMPEG_LIBAVCODEC - NAMES avcodec - PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - find_library(FFMPEG_LIBAVUTIL - NAMES avutil - PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - find_library(FFMPEG_LIBSWSCALE - NAMES swscale - PATHS ${_FFMPEG_SWSCALE_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVUTIL AND FFMPEG_LIBSWSCALE) - set(FFMPEG_FOUND TRUE) - endif() - - if(FFMPEG_FOUND) - set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBAVCODEC} - ${FFMPEG_LIBAVUTIL} - ${FFMPEG_LIBSWSCALE}) - endif() - - if(FFMPEG_FOUND) - if(NOT FFMPEG_FIND_QUIETLY) - message(STATUS - "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") - endif() + if(FFMPEG_DIR) + list(APPEND INCLUDE_PATHS + ${FFMPEG_DIR} + ${FFMPEG_DIR}/ffmpeg + ${FFMPEG_DIR}/lib${LIBNAME} + ${FFMPEG_DIR}/include/lib${LIBNAME} + ${FFMPEG_DIR}/include/ffmpeg + ${FFMPEG_DIR}/include + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + list(APPEND LIB_PATHS + ${FFMPEG_DIR} + ${FFMPEG_DIR}/lib + ${FFMPEG_DIR}/lib${LIBNAME} + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) else() - if(FFMPEG_FIND_REQUIRED) - message(FATAL_ERROR - "Could not find libavcodec or libavutil or libswscale") + list(APPEND INCLUDE_PATHS + /usr/local/include/ffmpeg + /usr/local/include/lib${LIBNAME} + /usr/include/ffmpeg + /usr/include/lib${LIBNAME} + /usr/include/ffmpeg/lib${LIBNAME} + ) + + list(APPEND LIB_PATHS + /usr/local/lib + /usr/lib + ) + endif() + + find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h + HINTS ${INCLUDE_PATHS} + ) + + find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME} + HINTS ${LIB_PATHS} + ) + + if(NOT FFMPEG_DIR AND (NOT FFmpeg_LIBRARY_${LIBNAME} OR NOT FFmpeg_INCLUDE_${LIBNAME})) + # Didn't find it in the usual paths, try pkg-config + find_package(PkgConfig QUIET) + pkg_check_modules(FFmpeg_PKGCONFIG_${LIBNAME} QUIET lib${LIBNAME}) + + find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h + ${FFmpeg_PKGCONFIG_${LIBNAME}_INCLUDE_DIRS} + ) + + find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME} + ${FFmpeg_PKGCONFIG_${LIBNAME}_LIBRARY_DIRS} + ) + endif() + + if(FFmpeg_INCLUDE_${LIBNAME} AND FFmpeg_LIBRARY_${LIBNAME}) + set(FFmpeg_INCLUDE_${LIBNAME} "${FFmpeg_INCLUDE_${LIBNAME}}" PARENT_SCOPE) + set(FFmpeg_LIBRARY_${LIBNAME} "${FFmpeg_LIBRARY_${LIBNAME}}" PARENT_SCOPE) + + # Extract FFmpeg version from version.h + foreach(v MAJOR MINOR MICRO) + set(FFmpeg_${LIBNAME}_VERSION_${v} 0) + endforeach() + string(TOUPPER ${LIBNAME} LIBNAME_UPPER) + file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version.h" _FFmpeg_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_(MAJOR|MINOR|MICRO) ") + set(_FFmpeg_VERSION_REGEX "([0-9]+)") + foreach(v MAJOR MINOR MICRO) + if("${_FFmpeg_VERSION_H_CONTENTS}" MATCHES "#define LIB${LIBNAME_UPPER}_VERSION_${v}[\\t ]+${_FFmpeg_VERSION_REGEX}") + set(FFmpeg_${LIBNAME}_VERSION_${v} "${CMAKE_MATCH_1}") + endif() + endforeach() + set(FFmpeg_${LIBNAME}_VERSION "${FFmpeg_${LIBNAME}_VERSION_MAJOR}.${FFmpeg_${LIBNAME}_VERSION_MINOR}.${FFmpeg_${LIBNAME}_VERSION_MICRO}") + set(FFmpeg_${c}_VERSION "${FFmpeg_${LIBNAME}_VERSION}" PARENT_SCOPE) + unset(_FFmpeg_VERSION_REGEX) + unset(_FFmpeg_VERSION_H_CONTENTS) + + set(FFmpeg_${c}_FOUND TRUE PARENT_SCOPE) + if(NOT FFmpeg_FIND_QUIETLY) + message("-- Found ${LIBNAME}: ${FFmpeg_INCLUDE_${LIBNAME}} ${FFmpeg_LIBRARY_${LIBNAME}} (version: ${FFmpeg_${LIBNAME}_VERSION})") endif() endif() +endfunction() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + find_ffmpeg(${c}) +endforeach() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + if(FFmpeg_${c}_FOUND) + list(APPEND FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_${c}}) + list(APPEND FFmpeg_LIBRARIES ${FFmpeg_LIBRARY_${c}}) + + add_library(FFmpeg::${c} IMPORTED UNKNOWN) + set_target_properties(FFmpeg::${c} PROPERTIES + IMPORTED_LOCATION ${FFmpeg_LIBRARY_${c}} + INTERFACE_INCLUDE_DIRECTORIES ${FFmpeg_INCLUDE_${c}} + ) + if(_FFmpeg_DEPS_${c}) + set(deps) + foreach(dep ${_FFmpeg_DEPS_${c}}) + list(APPEND deps FFmpeg::${dep}) + endforeach() + + set_target_properties(FFmpeg::${c} PROPERTIES + INTERFACE_LINK_LIBRARIES "${deps}" + ) + unset(deps) + endif() + endif() +endforeach() + +if(FFmpeg_INCLUDE_DIR) + list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIR) endif() + +foreach(c ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_INCLUDE_${c} FFmpeg_LIBRARY_${c}) +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FFmpeg + REQUIRED_VARS ${_FFmpeg_REQUIRED_VARS} + HANDLE_COMPONENTS +) + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + unset(_FFmpeg_DEPS_${c}) +endforeach() +unset(_FFmpeg_ALL_COMPONENTS) +unset(_FFmpeg_REQUIRED_VARS) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 01e284d8c..1434d0260 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -277,8 +277,8 @@ if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) add_dependencies(video_core ffmpeg-build) endif() -target_include_directories(video_core PRIVATE ${FFMPEG_INCLUDE_DIR}) -target_link_libraries(video_core PRIVATE ${FFMPEG_LIBRARIES}) +target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) +target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) From b7e6eca8b21cdfee5bec6734657314822bccb2e1 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 16:46:03 -0500 Subject: [PATCH 5/9] Address reviewer comments --- src/video_core/command_classes/codecs/codec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index c25d2ad2c..39bc923a5 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp @@ -13,7 +13,7 @@ #include "video_core/memory_manager.h" extern "C" { -#include "libavutil/opt.h" +#include } namespace Tegra { From 830612ef9e1f2f1e45288fd083a165ade4c3fdfe Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 18:03:20 -0500 Subject: [PATCH 6/9] CMakeLists: Fixes for linux-fresh Tells CMake to look for either nasm or yasm as it is required to build FFmpeg. Avoids a compile-time error by checking for it during configuration. Adds a workaround for Ubuntu Bionic's old version of make not communicating jobserver details properly. --- CMakeLists.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc3e93f80..6cd7e3e92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,6 +391,10 @@ if (YUZU_USE_BUNDLED_FFMPEG) # Build FFmpeg from externals message(STATUS "Using FFmpeg from externals") + # FFmpeg has source that requires one of nasm or yasm to assemble it. + # REQUIRED throws an error if not found here during configuration rather than during compilation. + find_program(ASSEMBLER NAMES nasm yasm REQUIRED) + set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile) @@ -448,11 +452,19 @@ if (YUZU_USE_BUNDLED_FFMPEG) ${FFmpeg_BUILD_DIR} ) + # Workaround for Ubuntu 18.04's older version of make not being able to call make as a child + # with context of the jobserver. Also helps ninja users. + execute_process( + COMMAND + nproc + OUTPUT_VARIABLE + SYSTEM_THREADS) + add_custom_command( OUTPUT ${FFmpeg_LIBRARIES} COMMAND - make + make -j${SYSTEM_THREADS} WORKING_DIRECTORY ${FFmpeg_BUILD_DIR} ) From 8b54e219c9dcdcb144c883494bba6e3a88dffb72 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 22:27:37 -0500 Subject: [PATCH 7/9] CMakeLists: Update to FFmpeg 4.3.1 for WIN32 Minimal binaries go brrrrrrr --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cd7e3e92..0b25a21de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -483,7 +483,7 @@ if (YUZU_USE_BUNDLED_FFMPEG) endif() else() # WIN32 # Use yuzu FFmpeg binaries - set(FFmpeg_EXT_NAME "ffmpeg-4.2.1") + set(FFmpeg_EXT_NAME "ffmpeg-4.3.1") set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}") download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "") set(FFmpeg_FOUND YES) From 527188391c825836c91bd26c4b953999eb8f2dde Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sat, 6 Feb 2021 03:14:11 -0500 Subject: [PATCH 8/9] CMakeLists: Use bundled FFmpeg as a fallback Sets YUZU_USE_BUNDLED_FFMPEG as a CMake dependent option that is OFF on Linux and ON for WIN32 targets. If FFmpeg is not found when YUZU_USE_BUNDLED_FFMPEG is OFF, the bundled module/binaries are used instead. Reverts earlier changes to FindFFmpeg a bit, mostly to keep parity with it's Citra version a bit. Now _FFmpeg_ALL_COMPONENTS lists all components. We overwrite FFmpeg_LIBRARIES and FFmpeg_INCLUDE_DIR after using the module. --- CMakeLists.txt | 42 +++++++++++++++++-------- externals/find-modules/FindFFmpeg.cmake | 21 ++++++++----- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b25a21de..ac7c3ce90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "EN option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) -option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled yuzu" ON) +CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled yuzu" ON "WIN32" OFF) option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) @@ -386,6 +386,32 @@ if (NOT LIBUSB_FOUND) set(LIBUSB_LIBRARIES usb) endif() +# List of all FFmpeg components required +set(FFmpeg_COMPONENTS + avcodec + avutil + swscale) + +if (NOT YUZU_USE_BUNDLED_FFMPEG) + # Use system installed FFmpeg + find_package(FFmpeg REQUIRED COMPONENTS ${FFmpeg_COMPONENTS}) + + if (FFmpeg_FOUND) + # Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries. + # Prevents shipping too many libraries with the AppImage. + set(FFmpeg_LIBRARIES "") + set(FFmpeg_INCLUDE_DIR "") + + foreach(COMPONENT ${FFmpeg_COMPONENTS}) + set(FFmpeg_LIBRARIES ${FFmpeg_LIBRARIES} ${FFmpeg_LIBRARY_${COMPONENT}} CACHE PATH "Paths to FFmpeg libraries" FORCE) + set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE) + endforeach() + else() + message(WARNING "FFmpeg not found, falling back to externals") + set(YUZU_USE_BUNDLED_FFMPEG ON) + endif() +endif() + if (YUZU_USE_BUNDLED_FFMPEG) if (NOT WIN32) # Build FFmpeg from externals @@ -407,11 +433,6 @@ if (YUZU_USE_BUNDLED_FFMPEG) set(FFmpeg_FOUND YES) endif() - set(FFmpeg_COMPONENTS - avcodec - avutil - swscale) - foreach(COMPONENT ${FFmpeg_COMPONENTS}) set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}") set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") @@ -496,15 +517,10 @@ if (YUZU_USE_BUNDLED_FFMPEG) ${FFmpeg_LIBRARY_DIR}/avutil.lib CACHE PATH "Paths to FFmpeg libraries" FORCE) endif() -else() - # Use system installed FFmpeg - find_package(FFmpeg REQUIRED) - - if (NOT FFmpeg_FOUND) - message(FATAL_ERROR "FFmpeg not found") - endif() endif() +unset(FFmpeg_COMPONENTS) + # Prefer the -pthread flag on Linux. set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) diff --git a/externals/find-modules/FindFFmpeg.cmake b/externals/find-modules/FindFFmpeg.cmake index 86a3f5a5a..61b6dc8d2 100644 --- a/externals/find-modules/FindFFmpeg.cmake +++ b/externals/find-modules/FindFFmpeg.cmake @@ -22,19 +22,24 @@ # # can be one of: # avcodec -# avdevice # Disabled -# avfilter # Disabled -# avformat # Disabled +# avdevice +# avfilter +# avformat # avutil -# postproc # Disabled -# swresample # Disabled +# postproc +# swresample # swscale # set(_FFmpeg_ALL_COMPONENTS - avcodec - avutil - swscale + avcodec + avdevice + avfilter + avformat + avutil + postproc + swresample + swscale ) set(_FFmpeg_DEPS_avcodec avutil) From 1a2e7c4dbd41171acf5e9408e7228c116f0c3b9f Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sat, 6 Feb 2021 03:19:07 -0500 Subject: [PATCH 9/9] ffmpeg: Checkout tag n4.3.1 Target a specific release version rather than some random development commit. --- externals/ffmpeg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/ffmpeg b/externals/ffmpeg index 81c462ad9..6b6b9e593 160000 --- a/externals/ffmpeg +++ b/externals/ffmpeg @@ -1 +1 @@ -Subproject commit 81c462ad95f143837a6a21126117515577f0977b +Subproject commit 6b6b9e593dd4d3aaf75f48d40a13ef03bdef9fdb