Compare commits

..

16 Commits

Author SHA1 Message Date
liushuyu
dd72e4dce4 CI: fix CI on Linux 2021-12-13 22:31:19 -07:00
liushuyu
a2d73eaa10 video_core/codecs: skip decoders that use hw frames ...
... this would resolve some edge-cases where multiple devices are
present and ffmpeg is unable to auto-supply the hw surfaces
2021-12-13 22:29:19 -07:00
liushuyu
37f1c76613 CI: fix MinGW installation step 2021-12-13 17:48:05 -07:00
liushuyu
f91b6fbbcb ffmpeg: move the whole tree into externals/ffmpeg/ffmpeg ...
* this resolves the todo items in the CMakeLists.txt
* a version requirement check for ffmpeg is added to catch issues early
* for future-proof reasons, nasm/yasm is now only required when build on
  x86/AMD64 systems
2021-12-13 17:48:05 -07:00
liushuyu
ccc0a1e621 cmake: refactor ffmpeg searching and handling logic on Linux 2021-12-13 17:48:05 -07:00
bunnei
7276aaf907 Merge pull request #7576 from lioncash/tasenum
tas_input: Minor cleanup
2021-12-13 14:47:24 -08:00
Lioncash
54ca48e8b7 tas_input: Avoid minor copies in Read/WriteCommandButtons()
We don't need to copy the whole pair
2021-12-13 11:45:19 -05:00
Lioncash
734fb180bb tas_input: Remove unnecessary semicolon
Resolves a -Wextra-semi warning
2021-12-13 11:45:19 -05:00
Lioncash
ddda6ae776 tas_input: Execute clear() even if empty
clear() when empty is simply a no-op, so we can get rid of the check
here and let the stdlib do it for us.
2021-12-13 11:45:18 -05:00
Lioncash
db9320e754 tas_input: Remove unnecessary includes
Gets rid of indirect includes and includes only what the interface
needs.
2021-12-13 11:45:18 -05:00
Lioncash
26ef76213c tas_input: std::move strings into vector
While we're in the same area, we can also avoid performing std::stoi in
a loop when it only needs to be performed once.
2021-12-13 11:45:15 -05:00
Lioncash
a515ede2af tas_input: Use istringstream over stringstream
This is only using the input facilities, so we don't need to use the
fully-fleged stringstream.
2021-12-13 10:57:53 -05:00
Lioncash
6be730bdcd tas_input: Use u8string_view instead of u8string
Same behavior, but without the potential for extra allocations.
2021-12-13 10:54:43 -05:00
Lioncash
37a8e2a67e tas_input: Remove unused std::smatch variable
This also means we can get rid of the dependency on <regex>
2021-12-13 10:50:24 -05:00
Lioncash
d52ad96ce3 tas_input: Amend -Wdocumentation warnings
Parameters shouldn't have the colon by their name.
2021-12-13 10:49:11 -05:00
Lioncash
c126b0718c tas_input: Make TasAxes enum an enum class
Prevents these values from potentially clashing with anything in other
headers.
2021-12-13 10:41:32 -05:00
11 changed files with 314 additions and 312 deletions

View File

@@ -41,12 +41,11 @@ for i in package/*.exe; do
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/"
python3 .ci/scripts/windows/scan_dll.py package/*.exe 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"
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/ ';'
# copy libraries from yuzu.exe path

6
.gitmodules vendored
View File

@@ -34,12 +34,12 @@
[submodule "opus"]
path = externals/opus/opus
url = https://github.com/xiph/opus.git
[submodule "ffmpeg"]
path = externals/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "externals/cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
[submodule "externals/ffmpeg/ffmpeg"]
path = externals/ffmpeg/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git

View File

@@ -514,7 +514,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg
find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS})
find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
if (FFmpeg_FOUND)
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
@@ -527,225 +527,11 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
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")
message(WARNING "FFmpeg not found or too old, falling back to externals")
set(YUZU_USE_BUNDLED_FFMPEG ON)
endif()
endif()
if (YUZU_USE_BUNDLED_FFMPEG)
if (NOT WIN32)
# TODO(lat9nq): Move this to externals/ffmpeg/CMakeLists.txt (and move externals/ffmpeg to
# externals/ffmpeg/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)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
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()
unset(FFmpeg_LIBRARIES CACHE)
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()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND AND CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
--extra-cflags=-I${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${FFNVCODEC_LIBRARIES}
${CUDA_LIBRARIES}
)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${FFNVCODEC_INCLUDE_DIRS}
${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LDFLAGS
${FFNVCODEC_LDFLAGS}
${CUDA_LDFLAGS}
)
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-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
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# 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)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# 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-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else() # WIN32
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
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_LDFLAGS "" CACHE STRING "FFmpeg linker flags" 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()
endif()
unset(FFmpeg_COMPONENTS)
# Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

View File

@@ -121,3 +121,8 @@ if (NOT opus_FOUND)
message(STATUS "opus 1.3 or newer not found, falling back to externals")
add_subdirectory(opus EXCLUDE_FROM_ALL)
endif()
# FFMpeg
if (YUZU_USE_BUNDLED_FFMPEG)
add_subdirectory(ffmpeg)
endif()

1
externals/ffmpeg vendored

Submodule externals/ffmpeg deleted from 79e8d17024

209
externals/ffmpeg/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,209 @@
if (NOT WIN32)
# Build FFmpeg from externals
message(STATUS "Using FFmpeg from externals")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64)")
# 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)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg/ffmpeg)
set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg-build)
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()
unset(FFmpeg_LIBRARIES CACHE)
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()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS})
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
# ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress
# here we handle the hard-linking senario where CUDA is linked during compilation
if (CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
message(STATUS "CUDA libraries found, hard-linking will be performed")
endif(CUDA_FOUND)
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-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
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# 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)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# 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-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else(WIN32)
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
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_LDFLAGS "" CACHE STRING "FFmpeg linker flags" 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(WIN32)
unset(FFmpeg_COMPONENTS)

1
externals/ffmpeg/ffmpeg vendored Submodule

Submodule externals/ffmpeg/ffmpeg added at dc91b913b6

View File

@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <cstring>
#include <regex>
#include <fmt/format.h>
#include "common/fs/file.h"
@@ -15,7 +14,7 @@
namespace InputCommon::TasInput {
enum TasAxes : u8 {
enum class Tas::TasAxis : u8 {
StickX,
StickY,
SubstickX,
@@ -66,7 +65,7 @@ Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engi
Tas::~Tas() {
Stop();
};
}
void Tas::LoadTasFiles() {
script_length = 0;
@@ -79,43 +78,43 @@ void Tas::LoadTasFiles() {
}
void Tas::LoadTasFile(size_t player_index, size_t file_index) {
if (!commands[player_index].empty()) {
commands[player_index].clear();
}
commands[player_index].clear();
std::string file = Common::FS::ReadStringFromFile(
Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
fmt::format("script{}-{}.txt", file_index, player_index + 1),
Common::FS::FileType::BinaryFile);
std::stringstream command_line(file);
std::istringstream command_line(file);
std::string line;
int frame_no = 0;
while (std::getline(command_line, line, '\n')) {
if (line.empty()) {
continue;
}
std::smatch m;
std::stringstream linestream(line);
std::string segment;
std::vector<std::string> seglist;
while (std::getline(linestream, segment, ' ')) {
seglist.push_back(segment);
std::vector<std::string> seg_list;
{
std::istringstream line_stream(line);
std::string segment;
while (std::getline(line_stream, segment, ' ')) {
seg_list.push_back(std::move(segment));
}
}
if (seglist.size() < 4) {
if (seg_list.size() < 4) {
continue;
}
while (frame_no < std::stoi(seglist.at(0))) {
commands[player_index].push_back({});
const auto num_frames = std::stoi(seg_list[0]);
while (frame_no < num_frames) {
commands[player_index].emplace_back();
frame_no++;
}
TASCommand command = {
.buttons = ReadCommandButtons(seglist.at(1)),
.l_axis = ReadCommandAxis(seglist.at(2)),
.r_axis = ReadCommandAxis(seglist.at(3)),
.buttons = ReadCommandButtons(seg_list[1]),
.l_axis = ReadCommandAxis(seg_list[2]),
.r_axis = ReadCommandAxis(seg_list[3]),
};
commands[player_index].push_back(command);
frame_no++;
@@ -123,16 +122,17 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) {
LOG_INFO(Input, "TAS file loaded! {} frames", frame_no);
}
void Tas::WriteTasFile(std::u8string file_name) {
void Tas::WriteTasFile(std::u8string_view file_name) {
std::string output_text;
for (size_t frame = 0; frame < record_commands.size(); frame++) {
const TASCommand& line = record_commands[frame];
output_text += fmt::format("{} {} {} {}\n", frame, WriteCommandButtons(line.buttons),
WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis));
}
const auto bytes_written = Common::FS::WriteStringToFile(
Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name,
Common::FS::FileType::TextFile, output_text);
const auto tas_file_name = Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name;
const auto bytes_written =
Common::FS::WriteStringToFile(tas_file_name, Common::FS::FileType::TextFile, output_text);
if (bytes_written == output_text.size()) {
LOG_INFO(Input, "TAS file written to file!");
} else {
@@ -205,10 +205,10 @@ void Tas::UpdateThread() {
const int button = static_cast<int>(i);
SetButton(identifier, button, button_status);
}
SetAxis(identifier, TasAxes::StickX, command.l_axis.x);
SetAxis(identifier, TasAxes::StickY, command.l_axis.y);
SetAxis(identifier, TasAxes::SubstickX, command.r_axis.x);
SetAxis(identifier, TasAxes::SubstickY, command.r_axis.y);
SetTasAxis(identifier, TasAxis::StickX, command.l_axis.x);
SetTasAxis(identifier, TasAxis::StickY, command.l_axis.y);
SetTasAxis(identifier, TasAxis::SubstickX, command.r_axis.x);
SetTasAxis(identifier, TasAxis::SubstickY, command.r_axis.y);
}
} else {
is_running = Settings::values.tas_loop.GetValue();
@@ -224,27 +224,28 @@ void Tas::ClearInput() {
}
TasAnalog Tas::ReadCommandAxis(const std::string& line) const {
std::stringstream linestream(line);
std::string segment;
std::vector<std::string> seglist;
while (std::getline(linestream, segment, ';')) {
seglist.push_back(segment);
std::vector<std::string> seg_list;
{
std::istringstream line_stream(line);
std::string segment;
while (std::getline(line_stream, segment, ';')) {
seg_list.push_back(std::move(segment));
}
}
const float x = std::stof(seglist.at(0)) / 32767.0f;
const float y = std::stof(seglist.at(1)) / 32767.0f;
const float x = std::stof(seg_list.at(0)) / 32767.0f;
const float y = std::stof(seg_list.at(1)) / 32767.0f;
return {x, y};
}
u64 Tas::ReadCommandButtons(const std::string& data) const {
std::stringstream button_text(data);
std::string line;
u64 Tas::ReadCommandButtons(const std::string& line) const {
std::istringstream button_text(line);
std::string button_line;
u64 buttons = 0;
while (std::getline(button_text, line, ';')) {
for (auto [text, tas_button] : text_to_tas_button) {
if (text == line) {
while (std::getline(button_text, button_line, ';')) {
for (const auto& [text, tas_button] : text_to_tas_button) {
if (text == button_line) {
buttons |= static_cast<u64>(tas_button);
break;
}
@@ -254,8 +255,8 @@ u64 Tas::ReadCommandButtons(const std::string& data) const {
}
std::string Tas::WriteCommandButtons(u64 buttons) const {
std::string returns = "";
for (auto [text_button, tas_button] : text_to_tas_button) {
std::string returns;
for (const auto& [text_button, tas_button] : text_to_tas_button) {
if ((buttons & static_cast<u64>(tas_button)) != 0) {
returns += fmt::format("{};", text_button);
}
@@ -267,6 +268,10 @@ std::string Tas::WriteCommandAxis(TasAnalog analog) const {
return fmt::format("{};{}", analog.x * 32767, analog.y * 32767);
}
void Tas::SetTasAxis(const PadIdentifier& identifier, TasAxis axis, f32 value) {
SetAxis(identifier, static_cast<int>(axis), value);
}
void Tas::StartStop() {
if (!Settings::values.tas_enable) {
return;

View File

@@ -5,11 +5,11 @@
#pragma once
#include <array>
#include <string>
#include <vector>
#include "common/common_types.h"
#include "common/settings_input.h"
#include "input_common/input_engine.h"
#include "input_common/main.h"
/*
To play back TAS scripts on Yuzu, select the folder with scripts in the configuration menu below
@@ -88,39 +88,39 @@ public:
/**
* Changes the input status that will be stored in each frame
* @param buttons: bitfield with the status of the buttons
* @param left_axis: value of the left axis
* @param right_axis: value of the right axis
* @param buttons Bitfield with the status of the buttons
* @param left_axis Value of the left axis
* @param right_axis Value of the right axis
*/
void RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis);
// Main loop that records or executes input
void UpdateThread();
// Sets the flag to start or stop the TAS command excecution and swaps controllers profiles
// Sets the flag to start or stop the TAS command execution and swaps controllers profiles
void StartStop();
// Stop the TAS and reverts any controller profile
// Stop the TAS and reverts any controller profile
void Stop();
// Sets the flag to reload the file and start from the begining in the next update
// Sets the flag to reload the file and start from the beginning in the next update
void Reset();
/**
* Sets the flag to enable or disable recording of inputs
* @return Returns true if the current recording status is enabled
* @returns true if the current recording status is enabled
*/
bool Record();
/**
* Saves contents of record_commands on a file
* @param overwrite_file: Indicates if player 1 should be overwritten
* @param overwrite_file Indicates if player 1 should be overwritten
*/
void SaveRecording(bool overwrite_file);
/**
* Returns the current status values of TAS playback/recording
* @return Tuple of
* @returns A Tuple of
* TasState indicating the current state out of Running ;
* Current playback progress ;
* Total length of script file currently loaded or being recorded
@@ -128,6 +128,8 @@ public:
std::tuple<TasState, size_t, size_t> GetStatus() const;
private:
enum class TasAxis : u8;
struct TASCommand {
u64 buttons{};
TasAnalog l_axis{};
@@ -137,29 +139,31 @@ private:
/// Loads TAS files from all players
void LoadTasFiles();
/** Loads TAS file from the specified player
* @param player_index: player number to save the script
* @param file_index: script number of the file
/**
* Loads TAS file from the specified player
* @param player_index Player number to save the script
* @param file_index Script number of the file
*/
void LoadTasFile(size_t player_index, size_t file_index);
/** Writes a TAS file from the recorded commands
* @param file_name: name of the file to be written
/**
* Writes a TAS file from the recorded commands
* @param file_name Name of the file to be written
*/
void WriteTasFile(std::u8string file_name);
void WriteTasFile(std::u8string_view file_name);
/**
* Parses a string containing the axis values. X and Y have a range from -32767 to 32767
* @param line: string containing axis values with the following format "x;y"
* @return Returns a TAS analog object with axis values with range from -1.0 to 1.0
* @param line String containing axis values with the following format "x;y"
* @returns A TAS analog object with axis values with range from -1.0 to 1.0
*/
TasAnalog ReadCommandAxis(const std::string& line) const;
/**
* Parses a string containing the button values. Each button is represented by it's text format
* specified in text_to_tas_button array
* @param line: string containing button name with the following format "a;b;c;d..."
* @return Returns a u64 with each bit representing the status of a button
* @param line string containing button name with the following format "a;b;c;d..."
* @returns A u64 with each bit representing the status of a button
*/
u64 ReadCommandButtons(const std::string& line) const;
@@ -170,17 +174,20 @@ private:
/**
* Converts an u64 containing the button status into the text equivalent
* @param buttons: bitfield with the status of the buttons
* @return Returns a string with the name of the buttons to be written to the file
* @param buttons Bitfield with the status of the buttons
* @returns A string with the name of the buttons to be written to the file
*/
std::string WriteCommandButtons(u64 buttons) const;
/**
* Converts an TAS analog object containing the axis status into the text equivalent
* @param data: value of the axis
* @return A string with the value of the axis to be written to the file
* @param analog Value of the axis
* @returns A string with the value of the axis to be written to the file
*/
std::string WriteCommandAxis(TasAnalog data) const;
std::string WriteCommandAxis(TasAnalog analog) const;
/// Sets an axis for a particular pad to the given value.
void SetTasAxis(const PadIdentifier& identifier, TasAxis axis, f32 value);
size_t script_length{0};
bool is_recording{false};

View File

@@ -130,6 +130,12 @@ bool Codec::CreateGpuAvDevice() {
}
if (config->methods & HW_CONFIG_METHOD && config->device_type == type) {
av_codec_ctx->pix_fmt = config->pix_fmt;
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
// skip zero-copy decoders, we don't currently support them
LOG_DEBUG(Service_NVDRV, "Skipping decoder {} with unsupported capability {}.",
av_hwdevice_get_type_name(type), config->methods);
continue;
}
LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type));
return true;
}

View File

@@ -475,26 +475,11 @@ void QtSoftwareKeyboardDialog::open() {
row = 0;
column = 0;
switch (bottom_osk_index) {
case BottomOSKIndex::LowerCase:
case BottomOSKIndex::UpperCase: {
const auto* const curr_button =
keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column];
const auto* const curr_button =
keyboard_buttons[static_cast<int>(bottom_osk_index)][row][column];
// This is a workaround for setFocus() randomly not showing focus in the UI
QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
break;
}
case BottomOSKIndex::NumberPad: {
const auto* const curr_button = numberpad_buttons[row][column];
// This is a workaround for setFocus() randomly not showing focus in the UI
QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
break;
}
default:
break;
}
// This is a workaround for setFocus() randomly not showing focus in the UI
QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
StartInputThread();
}