diff --git a/CMake/CheckLib.cmake b/CMake/CheckLib.cmake index b98357b99f..64c05e9ba0 100644 --- a/CMake/CheckLib.cmake +++ b/CMake/CheckLib.cmake @@ -56,74 +56,3 @@ macro(check_lib var pc lib) endif() endmacro() -macro(check_libav) - if(PKG_CONFIG_FOUND) - pkg_check_modules(LIBAV libavcodec>=54.35.0 libavformat>=54.20.4 - libswscale>=2.1.1 libavutil>=52.3.0) - endif() - - if(NOT LIBAV_FOUND) - if(WIN32) - add_library(avcodec STATIC IMPORTED) - set_target_properties(avcodec PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/include - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/lib/avcodec.lib - ) - - add_library(avformat STATIC IMPORTED) - set_target_properties(avformat PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/include - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/lib/avformat.lib - ) - - add_library(avutil STATIC IMPORTED) - set_target_properties(avutil PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/include - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/lib/avutil.lib - ) - - add_library(swresample STATIC IMPORTED) - set_target_properties(swresample PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/include - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/lib/swresample.lib - ) - - add_library(swscale STATIC IMPORTED) - set_target_properties(swscale PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/include - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/Externals/ffmpeg/lib/swscale.lib - ) - - set(LIBAV_FOUND ON) - set(LIBAV_LIBRARIES avcodec avformat avutil swresample swscale) - else() - # Attempt to find it through static means - set(LIBAV_LDFLAGS avformat avcodec swscale avutil) - set(CMAKE_REQUIRED_LIBRARIES ${LIBAV_LDFLAGS}) - CHECK_CXX_SOURCE_COMPILES( - "extern \"C\" { - #include - #include - #include - #include - } - int main(int argc, char **argv) - { - av_register_all(); - return 0; - }" - LIBAV_FOUND) - unset(CMAKE_REQUIRED_LIBRARIES) - endif() - endif() - - if(LIBAV_FOUND) - message(STATUS "libav/ffmpeg found, enabling AVI frame dumps") - add_definitions(-DHAVE_LIBAV) - if(LIBAV_INCLUDE_DIRS) - include_directories(${LIBAV_INCLUDE_DIRS}) - endif() - else() - message(STATUS "libav/ffmpeg not found, disabling AVI frame dumps") - endif() -endmacro() diff --git a/CMake/FindFFmpeg.cmake b/CMake/FindFFmpeg.cmake new file mode 100644 index 0000000000..af7711f6f3 --- /dev/null +++ b/CMake/FindFFmpeg.cmake @@ -0,0 +1,165 @@ +# FindFFmpeg +# ---------- +# +# Find the native FFmpeg includes and libraries +# +# This module defines the following variables: +# +# FFmpeg_INCLUDE_: where to find .h +# FFmpeg_LIBRARY_: where to find the library +# FFmpeg_INCLUDES: 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 +# avfilter +# avformat +# postproc +# swresample +# swscale +# + +set(_FFmpeg_ALL_COMPONENTS + avcodec + avdevice + avfilter + avformat + avutil + postproc + swresample + swscale +) + +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() + + 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() + 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) + set(FFmpeg_${c}_FOUND TRUE PARENT_SCOPE) + if(NOT FFmpeg_FIND_QUIETLY) + message("-- Found ${LIBNAME}: ${FFmpeg_INCLUDE_${LIBNAME}} ${FFmpeg_LIBRARY_${LIBNAME}}") + endif() + endif() +endfunction() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + find_ffmpeg(${c}) +endforeach() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + if(FFmpeg_${c}_FOUND) + list(APPEND FFmpeg_INCLUDES ${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_INCLUDES) + list(REMOVE_DUPLICATES FFmpeg_INCLUDES) +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/CMakeLists.txt b/CMakeLists.txt index 67424f11b0..380193676b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -477,12 +477,18 @@ if(USE_X11) pkg_check_modules(X11_INPUT REQUIRED xi>=1.5.0) endif() -if(ENCODE_FRAMEDUMPS) - check_libav() - if(LIBAV_FOUND) - LIST(APPEND LIBS ${LIBAV_LDFLAGS}) - endif() +if(ENCODE_FRAMEDUMPS) + if(WIN32) + set(FFMPEG_DIR Externals/ffmpeg) + endif() + find_package(FFmpeg COMPONENTS avcodec avformat avutil swscale) + if(FFmpeg_FOUND) + message(STATUS "libav/ffmpeg found, enabling AVI frame dumps") + add_definitions(-DHAVE_FFMPEG) + else() + message(STATUS "libav/ffmpeg not found, disabling AVI frame dumps") + endif() endif() if(NOT ANDROID) diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 915ae56104..a3fffacea6 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -191,7 +191,7 @@ static std::string DoState(PointerWrap& p) Gecko::DoState(p); p.DoMarker("Gecko"); -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) AVIDump::DoState(); #endif diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 087ce9552d..cafff392e1 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -239,7 +239,7 @@ static wxString internal_resolution_frame_dumping_desc = wxTRANSLATE( "the size of the window it is displayed within. If the aspect ratio is widescreen, the output " "image will be scaled horizontally to preserve the vertical resolution.\n\nIf unsure, leave " "this unchecked."); -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) static wxString use_ffv1_desc = wxTRANSLATE("Encode frame dumps using the FFV1 codec.\n\nIf unsure, leave this unchecked."); #endif @@ -894,7 +894,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) wxGetTranslation(dump_efb_desc), vconfig.bDumpEFBTarget)); szr_utility->Add(CreateCheckBox(page_advanced, _("Free Look"), wxGetTranslation(free_look_desc), vconfig.bFreeLook)); -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) szr_utility->Add(CreateCheckBox(page_advanced, _("Frame Dumps Use FFV1"), wxGetTranslation(use_ffv1_desc), vconfig.bUseFFV1)); #endif diff --git a/Source/Core/VideoCommon/AVIDump.h b/Source/Core/VideoCommon/AVIDump.h index fcc3ddb2ce..065a5d63d0 100644 --- a/Source/Core/VideoCommon/AVIDump.h +++ b/Source/Core/VideoCommon/AVIDump.h @@ -27,7 +27,7 @@ public: static void Stop(); static void DoState(); -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) static Frame FetchState(u64 ticks); #else static Frame FetchState(u64 ticks) { return {}; } diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 7eef4f715d..a50cd2774a 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -62,12 +62,14 @@ else() set(SRCS ${SRCS} TextureDecoder_Generic.cpp) endif() -if(LIBAV_FOUND OR WIN32) - set(SRCS ${SRCS} AVIDump.cpp) -endif() - add_dolphin_library(videocommon "${SRCS}" "${LIBS}") -if(LIBAV_FOUND) - target_link_libraries(videocommon PRIVATE ${LIBS} ${LIBAV_LIBRARIES}) +if(FFmpeg_FOUND) + target_sources(videocommon PRIVATE AVIDump.cpp) + target_link_libraries(videocommon PRIVATE + FFmpeg::avcodec + FFmpeg::avformat + FFmpeg::avutil + FFmpeg::swscale + ) endif() diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index ff390a8c7d..42f07ef403 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -774,7 +774,7 @@ bool Renderer::IsFrameDumping() if (m_screenshot_request.IsSet()) return true; -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) if (SConfig::GetInstance().m_DumpFrames) return true; #endif @@ -828,7 +828,7 @@ void Renderer::RunFrameDumps() bool frame_dump_started = false; // If Dolphin was compiled without libav, we only support dumping to images. -#if !defined(HAVE_LIBAV) && !defined(_WIN32) +#if !defined(HAVE_FFMPEG) if (dump_to_avi) { WARN_LOG(VIDEO, "AVI frame dump requested, but Dolphin was compiled without libav. " @@ -900,7 +900,7 @@ void Renderer::RunFrameDumps() } } -#if defined(HAVE_LIBAV) || defined(_WIN32) +#if defined(HAVE_FFMPEG) bool Renderer::StartFrameDumpToAVI(const FrameDumpConfig& config) { @@ -932,7 +932,7 @@ void Renderer::StopFrameDumpToAVI() { } -#endif // defined(HAVE_LIBAV) || defined(WIN32) +#endif // defined(HAVE_FFMPEG) std::string Renderer::GetFrameDumpNextImageFileName() const { diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 7e791f588e..2362aeaa85 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -50,6 +50,7 @@ $(ExternalsDir)wxWidgets3\Include;%(AdditionalIncludeDirectories) $(ExternalsDir)xxhash;%(AdditionalIncludeDirectories) $(ExternalsDir)zlib;%(AdditionalIncludeDirectories) + HAVE_FFMPEG;%(PreprocessorDefinitions) _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) USE_UPNP;USE_USBDK;__LIBUSB__;%(PreprocessorDefinitions) PSAPI_VERSION=1;_M_X86=1;%(PreprocessorDefinitions)