From bd9984b5f838a899b035398f7414576f6d98659f Mon Sep 17 00:00:00 2001 From: B3N30 Date: Sun, 16 Dec 2018 15:03:23 +0100 Subject: [PATCH] Addressed reviews --- .travis/linux-frozen/docker.sh | 2 +- .travis/linux-mingw/docker.sh | 2 +- .travis/linux/docker.sh | 2 +- .travis/macos/build.sh | 2 +- .travis/transifex/docker.sh | 2 +- CMakeLists.txt | 2 +- appveyor.yml | 4 +- src/audio_core/CMakeLists.txt | 2 +- src/audio_core/hle/aac_decoder.cpp | 129 ++++++++++++--------- src/audio_core/hle/aac_decoder.h | 2 +- src/audio_core/hle/decoder.cpp | 4 +- src/audio_core/hle/decoder.h | 2 +- src/audio_core/hle/ffmpeg_dl.cpp | 173 ++++++++++++++++++++++++++++ src/audio_core/hle/ffmpeg_dl.h | 179 ++++------------------------- 14 files changed, 282 insertions(+), 225 deletions(-) create mode 100644 src/audio_core/hle/ffmpeg_dl.cpp diff --git a/.travis/linux-frozen/docker.sh b/.travis/linux-frozen/docker.sh index 0c4e72b4f..a4814da1a 100755 --- a/.travis/linux-frozen/docker.sh +++ b/.travis/linux-frozen/docker.sh @@ -3,7 +3,7 @@ cd /citra mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=OFF +cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON make -j4 ctest -VV -C Release diff --git a/.travis/linux-mingw/docker.sh b/.travis/linux-mingw/docker.sh index 2514a5058..4a0e4304b 100755 --- a/.travis/linux-mingw/docker.sh +++ b/.travis/linux-mingw/docker.sh @@ -5,7 +5,7 @@ cd /citra echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf" mkdir build && cd build -cmake .. -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON +cmake .. -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=ON make -j4 echo "Tests skipped" diff --git a/.travis/linux/docker.sh b/.travis/linux/docker.sh index 64d8b9417..2a583d6a5 100755 --- a/.travis/linux/docker.sh +++ b/.travis/linux/docker.sh @@ -3,7 +3,7 @@ cd /citra mkdir build && cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=OFF +cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON make -j4 ctest -VV -C Release diff --git a/.travis/macos/build.sh b/.travis/macos/build.sh index bb3c687e6..7a4b32e4f 100755 --- a/.travis/macos/build.sh +++ b/.travis/macos/build.sh @@ -7,7 +7,7 @@ export Qt5_DIR=$(brew --prefix)/opt/qt5 export PATH="/usr/local/opt/ccache/libexec:$PATH" mkdir build && cd build -cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON +cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=ON make -j4 ctest -VV -C Release diff --git a/.travis/transifex/docker.sh b/.travis/transifex/docker.sh index f608f3848..003b298b6 100644 --- a/.travis/transifex/docker.sh +++ b/.travis/transifex/docker.sh @@ -26,7 +26,7 @@ tx --version cd /citra mkdir build && cd build -cmake .. -DENABLE_QT_TRANSLATION=ON -DGENERATE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_SDL2=OFF -DENABLE_FFMPEG=OFF +cmake .. -DENABLE_QT_TRANSLATION=ON -DGENERATE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_SDL2=OFF make translation cd .. diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d80b97b1..5e72baefe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) -option(ENABLE_FFMPEG "Enable FFmpeg decoder/encoder" ON) +option(ENABLE_FFMPEG "Enable FFmpeg decoder/encoder" OFF) option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF) diff --git a/appveyor.yml b/appveyor.yml index fcb824d74..3c8646a88 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,9 +43,9 @@ before_build: $COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING} if ($env:BUILD_TYPE -eq 'msvc') { # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning - cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON .. 2>&1 && exit 0' + cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=ON .. 2>&1 && exit 0' } else { - C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON .. 2>&1" + C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG=ON .. 2>&1" } - cd .. diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index a0edc355d..d00d23d98 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -29,7 +29,7 @@ add_library(audio_core STATIC $<$:sdl2_sink.cpp sdl2_sink.h> $<$:cubeb_sink.cpp cubeb_sink.h> - $<$:hle/aac_decoder.cpp hle/aac_decoder.h hle/ffmpeg_dl.h> + $<$:hle/aac_decoder.cpp hle/aac_decoder.h hle/ffmpeg_dl.cpp hle/ffmpeg_dl.h> ) create_target_directory_groups(audio_core) diff --git a/src/audio_core/hle/aac_decoder.cpp b/src/audio_core/hle/aac_decoder.cpp index db8a09065..774d1a8ee 100644 --- a/src/audio_core/hle/aac_decoder.cpp +++ b/src/audio_core/hle/aac_decoder.cpp @@ -20,28 +20,47 @@ private: std::optional Decode(const BinaryRequest& request); - bool initalized; + struct AVPacketDeleter { + void operator()(AVPacket* packet) const { + av_packet_free_dl(&packet); + } + }; + + struct AVCodecContextDeleter { + void operator()(AVCodecContext* context) const { + avcodec_free_context_dl(&context); + } + }; + + struct AVCodecParserContextDeleter { + void operator()(AVCodecParserContext* parser) const { + av_parser_close_dl(parser); + } + }; + + struct AVFrameDeleter { + void operator()(AVFrame* frame) const { + av_frame_free_dl(&frame); + } + }; + + bool initalized = false; bool have_ffmpeg_dl; Memory::MemorySystem& memory; AVCodec* codec; - AVCodecContext* av_context = nullptr; - AVCodecParserContext* parser = nullptr; - AVPacket* av_packet; - AVFrame* decoded_frame = nullptr; + std::unique_ptr av_context; + std::unique_ptr parser; + std::unique_ptr av_packet; + std::unique_ptr decoded_frame; }; AACDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { - initalized = false; - have_ffmpeg_dl = InitFFmpegDL(); } -AACDecoder::Impl::~Impl() { - if (initalized) - Clear(); -} +AACDecoder::Impl::~Impl() = default; std::optional AACDecoder::Impl::ProcessRequest(const BinaryRequest& request) { if (request.codec != DecoderCodec::AAC) { @@ -52,23 +71,19 @@ std::optional AACDecoder::Impl::ProcessRequest(const BinaryReque switch (request.cmd) { case DecoderCommand::Init: { return Initalize(request); - break; } case DecoderCommand::Decode: { return Decode(request); - break; } case DecoderCommand::Unknown: { BinaryResponse response; std::memcpy(&response, &request, sizeof(response)); response.unknown1 = 0x0; return response; - break; } default: LOG_ERROR(Audio_DSP, "Got unknown binary request: {}", static_cast(request.cmd)); return {}; - break; } } @@ -85,7 +100,7 @@ std::optional AACDecoder::Impl::Initalize(const BinaryRequest& r return response; } - av_packet = av_packet_alloc_dl(); + av_packet.reset(av_packet_alloc_dl()); codec = avcodec_find_decoder_dl(AV_CODEC_ID_AAC); if (!codec) { @@ -93,19 +108,19 @@ std::optional AACDecoder::Impl::Initalize(const BinaryRequest& r return response; } - parser = av_parser_init_dl(codec->id); + parser.reset(av_parser_init_dl(codec->id)); if (!parser) { LOG_ERROR(Audio_DSP, "Parser not found\n"); return response; } - av_context = avcodec_alloc_context3_dl(codec); + av_context.reset(avcodec_alloc_context3_dl(codec)); if (!av_context) { LOG_ERROR(Audio_DSP, "Could not allocate audio codec context\n"); return response; } - if (avcodec_open2_dl(av_context, codec, NULL) < 0) { + if (avcodec_open2_dl(av_context.get(), codec, nullptr) < 0) { LOG_ERROR(Audio_DSP, "Could not open codec\n"); return response; } @@ -119,23 +134,23 @@ void AACDecoder::Impl::Clear() { return; } - avcodec_free_context_dl(&av_context); - av_parser_close_dl(parser); - av_frame_free_dl(&decoded_frame); - av_packet_free_dl(&av_packet); + av_context.reset(); + parser.reset(); + decoded_frame.reset(); + av_packet.reset(); } std::optional AACDecoder::Impl::Decode(const BinaryRequest& request) { + BinaryResponse response; + response.codec = request.codec; + response.cmd = request.cmd; + response.size = request.size; + if (!initalized) { LOG_DEBUG(Audio_DSP, "Decoder not initalized"); - // This is a hack to continue games that are not compiled with the aac codec - BinaryResponse response; - response.codec = request.codec; - response.cmd = request.cmd; response.num_channels = 2; response.num_samples = 1024; - response.size = request.size; return response; } @@ -151,14 +166,16 @@ std::optional AACDecoder::Impl::Decode(const BinaryRequest& requ std::size_t data_size = request.size; while (data_size > 0) { if (!decoded_frame) { - if (!(decoded_frame = av_frame_alloc_dl())) { + decoded_frame.reset(av_frame_alloc_dl()); + if (!decoded_frame) { LOG_ERROR(Audio_DSP, "Could not allocate audio frame"); return {}; } } - int ret = av_parser_parse2_dl(parser, av_context, &av_packet->data, &av_packet->size, data, - data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); + int ret = + av_parser_parse2_dl(parser.get(), av_context.get(), &av_packet->data, &av_packet->size, + data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); if (ret < 0) { LOG_ERROR(Audio_DSP, "Error while parsing"); return {}; @@ -166,7 +183,7 @@ std::optional AACDecoder::Impl::Decode(const BinaryRequest& requ data += ret; data_size -= ret; - ret = avcodec_send_packet_dl(av_context, av_packet); + ret = avcodec_send_packet_dl(av_context.get(), av_packet.get()); if (ret < 0) { LOG_ERROR(Audio_DSP, "Error submitting the packet to the decoder"); return {}; @@ -174,7 +191,7 @@ std::optional AACDecoder::Impl::Decode(const BinaryRequest& requ if (av_packet->size) { while (ret >= 0) { - ret = avcodec_receive_frame_dl(av_context, decoded_frame); + ret = avcodec_receive_frame_dl(av_context.get(), decoded_frame.get()); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; else if (ret < 0) { @@ -187,16 +204,19 @@ std::optional AACDecoder::Impl::Decode(const BinaryRequest& requ return {}; } - ASSERT(decoded_frame->channels == out_streams.size()); + ASSERT(decoded_frame->channels <= out_streams.size()); std::size_t size = bytes_per_sample * (decoded_frame->nb_samples); + response.num_channels = decoded_frame->channels; + response.num_samples += decoded_frame->nb_samples; + // FFmpeg converts to 32 signed floating point PCM, we need s16 PCM so we need to // convert it f32 val_float; for (std::size_t current_pos(0); current_pos < size;) { - for (std::size_t channel(0); channel < out_streams.size(); channel++) { - std::memcpy(&val_float, decoded_frame->data[0] + current_pos, + for (std::size_t channel(0); channel < decoded_frame->channels; channel++) { + std::memcpy(&val_float, decoded_frame->data[channel] + current_pos, sizeof(val_float)); s16 val = static_cast(0x7FFF * val_float); out_streams[channel].push_back(val & 0xFF); @@ -208,28 +228,27 @@ std::optional AACDecoder::Impl::Decode(const BinaryRequest& requ } } - if (request.dst_addr_ch0 < Memory::FCRAM_PADDR || - request.dst_addr_ch0 + out_streams[0].size() > Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) { - LOG_ERROR(Audio_DSP, "Got out of bounds dst_addr_ch0 {:08x}", request.dst_addr_ch0); - return {}; + if (out_streams[0].size() != 0) { + if (request.dst_addr_ch0 < Memory::FCRAM_PADDR || + request.dst_addr_ch0 + out_streams[0].size() > + Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) { + LOG_ERROR(Audio_DSP, "Got out of bounds dst_addr_ch0 {:08x}", request.dst_addr_ch0); + return {}; + } + std::memcpy(memory.GetFCRAMPointer(request.dst_addr_ch0 - Memory::FCRAM_PADDR), + out_streams[0].data(), out_streams[0].size()); } - std::memcpy(memory.GetFCRAMPointer(request.dst_addr_ch0 - Memory::FCRAM_PADDR), - out_streams[0].data(), out_streams[0].size()); - if (request.dst_addr_ch1 < Memory::FCRAM_PADDR || - request.dst_addr_ch1 + out_streams[1].size() > Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) { - LOG_ERROR(Audio_DSP, "Got out of bounds dst_addr_ch1 {:08x}", request.dst_addr_ch1); - return {}; + if (out_streams[1].size() != 0) { + if (request.dst_addr_ch1 < Memory::FCRAM_PADDR || + request.dst_addr_ch1 + out_streams[1].size() > + Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) { + LOG_ERROR(Audio_DSP, "Got out of bounds dst_addr_ch1 {:08x}", request.dst_addr_ch1); + return {}; + } + std::memcpy(memory.GetFCRAMPointer(request.dst_addr_ch1 - Memory::FCRAM_PADDR), + out_streams[1].data(), out_streams[1].size()); } - std::memcpy(memory.GetFCRAMPointer(request.dst_addr_ch1 - Memory::FCRAM_PADDR), - out_streams[1].data(), out_streams[1].size()); - - BinaryResponse response; - response.codec = request.codec; - response.cmd = request.cmd; - response.num_channels = 2; - response.num_samples = decoded_frame->nb_samples; - response.size = request.size; return response; } diff --git a/src/audio_core/hle/aac_decoder.h b/src/audio_core/hle/aac_decoder.h index 96e47b61b..ec941dfb0 100644 --- a/src/audio_core/hle/aac_decoder.h +++ b/src/audio_core/hle/aac_decoder.h @@ -10,7 +10,7 @@ namespace AudioCore::HLE { class AACDecoder final : public DecoderBase { public: - AACDecoder(Memory::MemorySystem& memory); + explicit AACDecoder(Memory::MemorySystem& memory); ~AACDecoder() override; std::optional ProcessRequest(const BinaryRequest& request) override; diff --git a/src/audio_core/hle/decoder.cpp b/src/audio_core/hle/decoder.cpp index 4832aab73..e181e3cde 100644 --- a/src/audio_core/hle/decoder.cpp +++ b/src/audio_core/hle/decoder.cpp @@ -6,7 +6,9 @@ namespace AudioCore::HLE { -NullDecoder::NullDecoder() {} +DecoderBase::~DecoderBase(){}; + +NullDecoder::NullDecoder() = default; NullDecoder::~NullDecoder() = default; diff --git a/src/audio_core/hle/decoder.h b/src/audio_core/hle/decoder.h index fc2859760..a551df4eb 100644 --- a/src/audio_core/hle/decoder.h +++ b/src/audio_core/hle/decoder.h @@ -54,7 +54,7 @@ static_assert(sizeof(BinaryResponse) == 32, "Unexpected struct size for BinaryRe class DecoderBase { public: - virtual ~DecoderBase(){}; + virtual ~DecoderBase(); virtual std::optional ProcessRequest(const BinaryRequest& request) = 0; }; diff --git a/src/audio_core/hle/ffmpeg_dl.cpp b/src/audio_core/hle/ffmpeg_dl.cpp new file mode 100644 index 000000000..0a3b2148c --- /dev/null +++ b/src/audio_core/hle/ffmpeg_dl.cpp @@ -0,0 +1,173 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#ifdef _WIN32 + +#include +#include "audio_core/hle/ffmpeg_dl.h" +#include "common/file_util.h" +#include "common/logging/log.h" + +struct LibraryDeleter { + typedef HMODULE pointer; + void operator()(HMODULE h) { + if (h != nullptr) + FreeLibrary(h); + } +}; + +std::unique_ptr dll_util{nullptr}; +std::unique_ptr dll_codec{nullptr}; + +FuncDL av_get_bytes_per_sample_dl; +FuncDL av_frame_alloc_dl; +FuncDL av_frame_free_dl; +FuncDL avcodec_alloc_context3_dl; +FuncDL avcodec_free_context_dl; +FuncDL avcodec_open2_dl; +FuncDL av_packet_alloc_dl; +FuncDL av_packet_free_dl; +FuncDL avcodec_find_decoder_dl; +FuncDL avcodec_send_packet_dl; +FuncDL avcodec_receive_frame_dl; +FuncDL av_parser_init_dl; +FuncDL + av_parser_parse2_dl; +FuncDL av_parser_close_dl; + +bool InitFFmpegDL() { + std::string dll_path = FileUtil::GetUserPath(FileUtil::UserPath::DLLDir); + FileUtil::CreateDir(dll_path); + std::wstring w_dll_path = std::wstring(dll_path.begin(), dll_path.end()); + SetDllDirectoryW(w_dll_path.c_str()); + + dll_util.reset(LoadLibrary("avutil-56.dll")); + if (!dll_util) { + DWORD error_message_id = GetLastError(); + LPSTR message_buffer = nullptr; + size_t size = + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&message_buffer), 0, nullptr); + + std::string message(message_buffer, size); + + LocalFree(message_buffer); + LOG_ERROR(Audio_DSP, "Could not load avutil-56.dll: {}", message); + return false; + } + + dll_codec.reset(LoadLibrary("avcodec-58.dll")); + if (!dll_codec) { + DWORD error_message_id = GetLastError(); + LPSTR message_buffer = nullptr; + size_t size = + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&message_buffer), 0, nullptr); + + std::string message(message_buffer, size); + + LocalFree(message_buffer); + LOG_ERROR(Audio_DSP, "Could not load avcodec-58.dll: {}", message); + return false; + } + av_get_bytes_per_sample_dl = + FuncDL(dll_util.get(), "av_get_bytes_per_sample"); + if (!av_get_bytes_per_sample_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_get_bytes_per_sample"); + return false; + } + + av_frame_alloc_dl = FuncDL(dll_util.get(), "av_frame_alloc"); + if (!av_frame_alloc_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_frame_alloc"); + return false; + } + + av_frame_free_dl = FuncDL(dll_util.get(), "av_frame_free"); + if (!av_frame_free_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_frame_free"); + return false; + } + + avcodec_alloc_context3_dl = + FuncDL(dll_codec.get(), "avcodec_alloc_context3"); + if (!avcodec_alloc_context3_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_alloc_context3"); + return false; + } + + avcodec_free_context_dl = + FuncDL(dll_codec.get(), "avcodec_free_context"); + if (!av_get_bytes_per_sample_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_free_context"); + return false; + } + + avcodec_open2_dl = FuncDL( + dll_codec.get(), "avcodec_open2"); + if (!avcodec_open2_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_open2"); + return false; + } + av_packet_alloc_dl = FuncDL(dll_codec.get(), "av_packet_alloc"); + if (!av_packet_alloc_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_packet_alloc"); + return false; + } + + av_packet_free_dl = FuncDL(dll_codec.get(), "av_packet_free"); + if (!av_packet_free_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_packet_free"); + return false; + } + + avcodec_find_decoder_dl = FuncDL(dll_codec.get(), "avcodec_find_decoder"); + if (!avcodec_find_decoder_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_find_decoder"); + return false; + } + + avcodec_send_packet_dl = + FuncDL(dll_codec.get(), "avcodec_send_packet"); + if (!avcodec_send_packet_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_send_packet"); + return false; + } + + avcodec_receive_frame_dl = + FuncDL(dll_codec.get(), "avcodec_receive_frame"); + if (!avcodec_receive_frame_dl) { + LOG_ERROR(Audio_DSP, "Can not load function avcodec_receive_frame"); + return false; + } + + av_parser_init_dl = FuncDL(dll_codec.get(), "av_parser_init"); + if (!av_parser_init_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_parser_init"); + return false; + } + + av_parser_parse2_dl = + FuncDL(dll_codec.get(), "av_parser_parse2"); + if (!av_parser_parse2_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_parser_parse2"); + return false; + } + + av_parser_close_dl = FuncDL(dll_codec.get(), "av_parser_close"); + if (!av_parser_close_dl) { + LOG_ERROR(Audio_DSP, "Can not load function av_parser_close"); + return false; + } + + return true; +} + +#endif // _Win32 diff --git a/src/audio_core/hle/ffmpeg_dl.h b/src/audio_core/hle/ffmpeg_dl.h index 61af403b9..57e150f95 100644 --- a/src/audio_core/hle/ffmpeg_dl.h +++ b/src/audio_core/hle/ffmpeg_dl.h @@ -8,9 +8,6 @@ #include #endif // _WIN32 -#include "common/file_util.h" -#include "common/logging/log.h" - extern "C" { #include "libavcodec/avcodec.h" } @@ -20,9 +17,9 @@ extern "C" { template struct FuncDL { FuncDL() = default; - FuncDL(HMODULE dll, const char* name) { + FuncDL(void* dll, const char* name) { if (dll) { - ptr_function = reinterpret_cast(GetProcAddress(dll, name)); + ptr_function = reinterpret_cast(GetProcAddress((HMODULE)dll, name)); } } @@ -30,167 +27,33 @@ struct FuncDL { return ptr_function; } - operator bool() const { + explicit operator bool() const { return ptr_function != nullptr; } T* ptr_function = nullptr; }; -FuncDL av_get_bytes_per_sample_dl; -FuncDL av_frame_alloc_dl; -FuncDL av_frame_free_dl; -FuncDL avcodec_alloc_context3_dl; -FuncDL avcodec_free_context_dl; -FuncDL avcodec_open2_dl; -FuncDL av_packet_alloc_dl; -FuncDL av_packet_free_dl; -FuncDL avcodec_find_decoder_dl; -FuncDL avcodec_send_packet_dl; -FuncDL avcodec_receive_frame_dl; -FuncDL av_parser_init_dl; -FuncDL +extern FuncDL av_get_bytes_per_sample_dl; +extern FuncDL av_frame_alloc_dl; +extern FuncDL av_frame_free_dl; +extern FuncDL avcodec_alloc_context3_dl; +extern FuncDL avcodec_free_context_dl; +extern FuncDL avcodec_open2_dl; +extern FuncDL av_packet_alloc_dl; +extern FuncDL av_packet_free_dl; +extern FuncDL avcodec_find_decoder_dl; +extern FuncDL avcodec_send_packet_dl; +extern FuncDL avcodec_receive_frame_dl; +extern FuncDL av_parser_init_dl; +extern FuncDL av_parser_parse2_dl; -FuncDL av_parser_close_dl; +extern FuncDL av_parser_close_dl; -bool InitFFmpegDL() { +bool InitFFmpegDL(); - FileUtil::CreateDir(FileUtil::GetUserPath(FileUtil::UserPath::DLLDir)); - SetDllDirectoryA(FileUtil::GetUserPath(FileUtil::UserPath::DLLDir).c_str()); - - HMODULE dll_util = nullptr; - dll_util = LoadLibrary("avutil-56.dll"); - if (!dll_util) { - DWORD errorMessageID = GetLastError(); - LPSTR messageBuffer = nullptr; - size_t size = - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&messageBuffer, 0, NULL); - - std::string message(messageBuffer, size); - - // Free the buffer. - LocalFree(messageBuffer); - LOG_ERROR(Audio_DSP, "Could not load avutil-56.dll: {}", message); - return false; - } - - HMODULE dll_codec = nullptr; - dll_codec = LoadLibrary("avcodec-58.dll"); - if (!dll_codec) { - DWORD errorMessageID = GetLastError(); - LPSTR messageBuffer = nullptr; - size_t size = - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&messageBuffer, 0, NULL); - - std::string message(messageBuffer, size); - - // Free the buffer. - LocalFree(messageBuffer); - LOG_ERROR(Audio_DSP, "Could not load avcodec-58.dll: {}", message); - return false; - } - av_get_bytes_per_sample_dl = FuncDL(dll_util, "av_get_bytes_per_sample"); - if (!av_get_bytes_per_sample_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_get_bytes_per_sample"); - return false; - } - - av_frame_alloc_dl = FuncDL(dll_util, "av_frame_alloc"); - if (!av_frame_alloc_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_frame_alloc"); - return false; - } - - av_frame_free_dl = FuncDL(dll_util, "av_frame_free"); - if (!av_frame_free_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_frame_free"); - return false; - } - - avcodec_alloc_context3_dl = - FuncDL(dll_codec, "avcodec_alloc_context3"); - if (!avcodec_alloc_context3_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_alloc_context3"); - return false; - } - - avcodec_free_context_dl = FuncDL(dll_codec, "avcodec_free_context"); - if (!av_get_bytes_per_sample_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_free_context"); - return false; - } - - avcodec_open2_dl = - FuncDL(dll_codec, "avcodec_open2"); - if (!avcodec_open2_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_open2"); - return false; - } - av_packet_alloc_dl = FuncDL(dll_codec, "av_packet_alloc"); - if (!av_packet_alloc_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_packet_alloc"); - return false; - } - - av_packet_free_dl = FuncDL(dll_codec, "av_packet_free"); - if (!av_packet_free_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_packet_free"); - return false; - } - - avcodec_find_decoder_dl = FuncDL(dll_codec, "avcodec_find_decoder"); - if (!avcodec_find_decoder_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_find_decoder"); - return false; - } - - avcodec_send_packet_dl = - FuncDL(dll_codec, "avcodec_send_packet"); - if (!avcodec_send_packet_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_send_packet"); - return false; - } - - avcodec_receive_frame_dl = - FuncDL(dll_codec, "avcodec_receive_frame"); - if (!avcodec_receive_frame_dl) { - LOG_ERROR(Audio_DSP, "Can not load function avcodec_receive_frame"); - return false; - } - - av_parser_init_dl = FuncDL(dll_codec, "av_parser_init"); - if (!av_parser_init_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_parser_init"); - return false; - } - - av_parser_parse2_dl = - FuncDL(dll_codec, "av_parser_parse2"); - if (!av_parser_parse2_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_parser_parse2"); - return false; - } - - av_parser_close_dl = FuncDL(dll_codec, "av_parser_close"); - if (!av_parser_close_dl) { - LOG_ERROR(Audio_DSP, "Can not load function av_parser_close"); - return false; - } - - return true; -} - -#endif // _Win32 - -#if defined(__APPLE__) || defined(__linux__) +#else // _Win32 // No dynamic loading for Unix and Apple @@ -213,4 +76,4 @@ bool InitFFmpegDL() { return true; } -#endif // defined(__APPLE__) || defined(__linux__) +#endif // _Win32