From 691ab820b8dcec37154dc584c6f5cfac095edd16 Mon Sep 17 00:00:00 2001 From: wangqr Date: Tue, 13 Jul 2021 10:32:40 -0400 Subject: [PATCH 1/5] Handle exceptions from AviSynthWrapper ctor --- src/audio_provider_avs.cpp | 5 ++++- src/video_provider_avs.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/audio_provider_avs.cpp b/src/audio_provider_avs.cpp index b94cb4df4..35981b1d5 100644 --- a/src/audio_provider_avs.cpp +++ b/src/audio_provider_avs.cpp @@ -63,7 +63,7 @@ public: bool NeedsCache() const override { return true; } }; -AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) { +AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) try { agi::acs::CheckFileRead(filename); std::lock_guard lock(avs_wrapper.GetMutex()); @@ -100,6 +100,9 @@ AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) { throw agi::AudioProviderError("Avisynth error: " + errmsg); } } +catch (AvisynthError& err) { + throw agi::AudioProviderError("Avisynth error: " + std::string(err.msg)); +} void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { // Check if it has audio diff --git a/src/video_provider_avs.cpp b/src/video_provider_avs.cpp index dabcdaa68..7c779e800 100644 --- a/src/video_provider_avs.cpp +++ b/src/video_provider_avs.cpp @@ -93,7 +93,7 @@ public: bool HasAudio() const override { return has_audio; } }; -AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) { +AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try { agi::acs::CheckFileRead(filename); std::lock_guard lock(avs.GetMutex()); @@ -182,6 +182,9 @@ file_exit: throw VideoOpenError("Avisynth error: " + std::string(err.msg)); } } +catch (AvisynthError const& err) { + throw VideoProviderError("Avisynth error: " + std::string(err.msg)); +} void AvisynthVideoProvider::Init(std::string const& colormatrix) { auto script = source_clip; From e2a49b3313d9961d58b3e0366fe59001302d1b5c Mon Sep 17 00:00:00 2001 From: wangqr Date: Sat, 2 Nov 2019 22:26:02 -0400 Subject: [PATCH 2/5] Avisynth audio provider: add option to allow no downmix --- src/audio_provider_avs.cpp | 12 +++++++----- src/preferences.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/audio_provider_avs.cpp b/src/audio_provider_avs.cpp index 35981b1d5..d249aa3d3 100644 --- a/src/audio_provider_avs.cpp +++ b/src/audio_provider_avs.cpp @@ -110,12 +110,14 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { if (!vi.HasAudio()) throw agi::AudioDataNotFound("No audio found."); IScriptEnvironment *env = avs_wrapper.GetEnv(); + AVSValue script; // Convert to one channel - AVSValue script = env->Invoke(OPT_GET("Audio/Downmixer")->GetString().c_str(), clip); + if (OPT_GET("Audio/Downmixer")->GetString() != "None") + script = env->Invoke(OPT_GET("Audio/Downmixer")->GetString().c_str(), clip); + else + script = clip; - // Convert to 16 bits per sample - script = env->Invoke("ConvertAudioTo16bit", script); vi = script.AsClip()->GetVideoInfo(); // Convert sample rate @@ -135,8 +137,8 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { channels = vi.AudioChannels(); decoded_samples = num_samples = vi.num_audio_samples; sample_rate = vi.SamplesPerSecond(); - bytes_per_sample = vi.BytesPerAudioSample(); - float_samples = false; + bytes_per_sample = vi.BytesPerChannelSample(); + float_samples = vi.IsSampleType(SAMPLE_FLOAT); this->clip = tempclip; } diff --git a/src/preferences.cpp b/src/preferences.cpp index 38f1ac285..07a21a420 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -387,8 +387,8 @@ void Advanced_Audio(wxTreebook *book, Preferences *parent) { #ifdef WITH_AVISYNTH auto avisynth = p->PageSizer("Avisynth"); - const wxString adm_arr[3] = { "ConvertToMono", "GetLeftChannel", "GetRightChannel" }; - wxArrayString adm_choice(3, adm_arr); + const wxString adm_arr[4] = { "None", "ConvertToMono", "GetLeftChannel", "GetRightChannel" }; + wxArrayString adm_choice(4, adm_arr); p->OptionChoice(avisynth, _("Avisynth down-mixer"), adm_choice, "Audio/Downmixer"); p->OptionAdd(avisynth, _("Force sample rate"), "Provider/Audio/AVS/Sample Rate"); #endif From fe285678a397d28f791dfdbad8c1b64401788b6a Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Fri, 6 Mar 2020 00:15:07 -0500 Subject: [PATCH 3/5] avisynth: Allow compilation on Linux Co-authored-by: wangqr --- meson.build | 8 ++++-- src/avisynth_wrap.cpp | 40 ++++++++++++++++++++++++---- src/libresrc/default_config.json | 2 +- src/libresrc/osx/default_config.json | 2 +- src/meson.build | 7 ++--- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/meson.build b/meson.build index 39cc7de00..50ec01dde 100644 --- a/meson.build +++ b/meson.build @@ -220,9 +220,9 @@ foreach dep: [ endif endforeach -if host_machine.system() == 'windows' and get_option('avisynth').enabled() +if get_option('avisynth').enabled() conf.set('WITH_AVISYNTH', 1) # bundled separately with installer - deps += cc.find_library('avifil32', required: true) + dep_avail += 'AviSynth' avs_opt = cmake.subproject_options() avs_opt.add_cmake_defines({ @@ -231,6 +231,10 @@ if host_machine.system() == 'windows' and get_option('avisynth').enabled() avs = cmake.subproject('avisynth', options: avs_opt) deps_inc += avs.include_directories('AviSynth-Headers') + + if host_machine.system() == 'windows' + deps += cc.find_library('avifil32', required: true) + endif endif if host_machine.system() == 'windows' and not get_option('directsound').disabled() diff --git a/src/avisynth_wrap.cpp b/src/avisynth_wrap.cpp index fd2246f77..a3b6a3de6 100644 --- a/src/avisynth_wrap.cpp +++ b/src/avisynth_wrap.cpp @@ -40,10 +40,24 @@ #include +#ifndef _WIN32 +#include +#endif + +#ifdef _WIN32 +#define AVISYNTH_SO "avisynth.dll" +#else +#define AVISYNTH_SO "libavisynth.so" +#endif + // Allocate storage for and initialise static members namespace { int avs_refcount = 0; +#ifdef _WIN32 HINSTANCE hLib = nullptr; +#else + void* hLib = nullptr; +#endif IScriptEnvironment *env = nullptr; std::mutex AviSynthMutex; } @@ -54,14 +68,26 @@ typedef IScriptEnvironment* __stdcall FUNC(int); AviSynthWrapper::AviSynthWrapper() { if (!avs_refcount++) { - hLib = LoadLibrary(L"avisynth.dll"); +#ifdef _WIN32 +#define CONCATENATE(x, y) x ## y +#define _Lstr(x) CONCATENATE(L, x) + hLib = LoadLibraryW(_Lstr(AVISYNTH_SO)); +#undef _Lstr +#undef CONCATENATE +#else + hLib = dlopen(AVISYNTH_SO, RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); +#endif if (!hLib) - throw AvisynthError("Could not load avisynth.dll"); + throw AvisynthError("Could not load " AVISYNTH_SO); - FUNC *CreateScriptEnv = (FUNC*)GetProcAddress(hLib, "CreateScriptEnvironment"); +#ifdef _WIN32 + FUNC* CreateScriptEnv = (FUNC*)GetProcAddress(hLib, "CreateScriptEnvironment"); +#else + FUNC* CreateScriptEnv = (FUNC*)dlsym(hLib, "CreateScriptEnvironment"); +#endif if (!CreateScriptEnv) - throw AvisynthError("Failed to get address of CreateScriptEnv from avisynth.dll"); + throw AvisynthError("Failed to get address of CreateScriptEnv from " AVISYNTH_SO); env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION); @@ -80,8 +106,12 @@ AviSynthWrapper::AviSynthWrapper() { AviSynthWrapper::~AviSynthWrapper() { if (!--avs_refcount) { delete env; - AVS_linkage = nullptr; +#ifdef _WIN32 FreeLibrary(hLib); +#else + dlclose(hLib); +#endif + AVS_linkage = nullptr; } } diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index f83002436..fbc98dc2e 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -335,7 +335,7 @@ } }, "Avisynth" : { - "Memory Max" : 128 + "Memory Max" : 1024 }, "FFmpegSource" : { "Cache" : { diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index 66cecd520..7d0cb9b6a 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -335,7 +335,7 @@ } }, "Avisynth" : { - "Memory Max" : 128 + "Memory Max" : 1024 }, "FFmpegSource" : { "Cache" : { diff --git a/src/meson.build b/src/meson.build index 9592cf6e0..b5791e558 100644 --- a/src/meson.build +++ b/src/meson.build @@ -171,11 +171,8 @@ if host_machine.system() == 'darwin' ) elif host_machine.system() == 'windows' aegisub_src += files( - 'avisynth_wrap.cpp', 'font_file_lister_gdi.cpp', # 'libass_gdi_fontselect.cpp', - 'audio_provider_avs.cpp', - 'video_provider_avs.cpp', ) if cc.has_header('wingdi.h') @@ -238,6 +235,10 @@ opt_src = [ 'video_provider_ffmpegsource.cpp', 'ffmpegsource_common.cpp']], + ['AviSynth', ['avisynth_wrap.cpp', + 'audio_provider_avs.cpp', + 'video_provider_avs.cpp']], + ['Hunspell', 'spellchecker_hunspell.cpp'], ] From ce1b3a0158c5c6407e58d8ff46f7e5d30f397fa6 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Tue, 9 Aug 2022 02:43:43 +0200 Subject: [PATCH 4/5] avisynth: Validate downmix option Because... let's maybe not let users make Aegisub call arbitrary symbols in avisynth.dll/so just by editing the config.json. --- src/audio_provider_avs.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/audio_provider_avs.cpp b/src/audio_provider_avs.cpp index d249aa3d3..0daa77e8e 100644 --- a/src/audio_provider_avs.cpp +++ b/src/audio_provider_avs.cpp @@ -113,8 +113,9 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { AVSValue script; // Convert to one channel - if (OPT_GET("Audio/Downmixer")->GetString() != "None") - script = env->Invoke(OPT_GET("Audio/Downmixer")->GetString().c_str(), clip); + std::string downmixtype = OPT_GET("Audio/Downmixer")->GetString(); + if (downmixtype == "ConvertToMono" || downmixtype == "GetLeftChannel" || downmixtype == "GetRightChannel") + script = env->Invoke(downmixtype.c_str(), clip); else script = clip; From ad443dd1186226f9542e85524c2dda656a2efff6 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Sat, 13 Aug 2022 22:53:58 +0200 Subject: [PATCH 5/5] avisynth: Properly destruct the IScriptEnvironment Starting with AVISYNTH_INTERFACE_VERSION=5, this is how script environments should be deleted. The previous code was causing crashes when unloading AviSynth in certain scenarios, such as when failing to open a file due to an incorrect path. --- src/avisynth_wrap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/avisynth_wrap.cpp b/src/avisynth_wrap.cpp index a3b6a3de6..eb957fa3c 100644 --- a/src/avisynth_wrap.cpp +++ b/src/avisynth_wrap.cpp @@ -105,7 +105,7 @@ AviSynthWrapper::AviSynthWrapper() { AviSynthWrapper::~AviSynthWrapper() { if (!--avs_refcount) { - delete env; + env->DeleteScriptEnvironment(); #ifdef _WIN32 FreeLibrary(hLib); #else