Merge branch 'avisynth' into feature

This commit is contained in:
arch1t3cht 2022-08-13 23:03:33 +02:00
commit 53466be0ca
8 changed files with 66 additions and 22 deletions

View File

@ -224,9 +224,9 @@ foreach dep: [
endif endif
endforeach 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 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 = cmake.subproject_options()
avs_opt.add_cmake_defines({ avs_opt.add_cmake_defines({
@ -235,6 +235,10 @@ if host_machine.system() == 'windows' and get_option('avisynth').enabled()
avs = cmake.subproject('avisynth', options: avs_opt) avs = cmake.subproject('avisynth', options: avs_opt)
deps_inc += avs.include_directories('AviSynth-Headers') deps_inc += avs.include_directories('AviSynth-Headers')
if host_machine.system() == 'windows'
deps += cc.find_library('avifil32', required: true)
endif
endif endif
if host_machine.system() == 'windows' and not get_option('directsound').disabled() if host_machine.system() == 'windows' and not get_option('directsound').disabled()

View File

@ -63,7 +63,7 @@ public:
bool NeedsCache() const override { return true; } 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); agi::acs::CheckFileRead(filename);
std::lock_guard<std::mutex> lock(avs_wrapper.GetMutex()); std::lock_guard<std::mutex> lock(avs_wrapper.GetMutex());
@ -100,6 +100,9 @@ AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) {
throw agi::AudioProviderError("Avisynth error: " + errmsg); throw agi::AudioProviderError("Avisynth error: " + errmsg);
} }
} }
catch (AvisynthError& err) {
throw agi::AudioProviderError("Avisynth error: " + std::string(err.msg));
}
void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
// Check if it has audio // Check if it has audio
@ -107,12 +110,15 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
if (!vi.HasAudio()) throw agi::AudioDataNotFound("No audio found."); if (!vi.HasAudio()) throw agi::AudioDataNotFound("No audio found.");
IScriptEnvironment *env = avs_wrapper.GetEnv(); IScriptEnvironment *env = avs_wrapper.GetEnv();
AVSValue script;
// Convert to one channel // Convert to one channel
AVSValue 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;
// Convert to 16 bits per sample
script = env->Invoke("ConvertAudioTo16bit", script);
vi = script.AsClip()->GetVideoInfo(); vi = script.AsClip()->GetVideoInfo();
// Convert sample rate // Convert sample rate
@ -132,8 +138,8 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
channels = vi.AudioChannels(); channels = vi.AudioChannels();
decoded_samples = num_samples = vi.num_audio_samples; decoded_samples = num_samples = vi.num_audio_samples;
sample_rate = vi.SamplesPerSecond(); sample_rate = vi.SamplesPerSecond();
bytes_per_sample = vi.BytesPerAudioSample(); bytes_per_sample = vi.BytesPerChannelSample();
float_samples = false; float_samples = vi.IsSampleType(SAMPLE_FLOAT);
this->clip = tempclip; this->clip = tempclip;
} }

View File

@ -40,10 +40,24 @@
#include <mutex> #include <mutex>
#ifndef _WIN32
#include <dlfcn.h>
#endif
#ifdef _WIN32
#define AVISYNTH_SO "avisynth.dll"
#else
#define AVISYNTH_SO "libavisynth.so"
#endif
// Allocate storage for and initialise static members // Allocate storage for and initialise static members
namespace { namespace {
int avs_refcount = 0; int avs_refcount = 0;
#ifdef _WIN32
HINSTANCE hLib = nullptr; HINSTANCE hLib = nullptr;
#else
void* hLib = nullptr;
#endif
IScriptEnvironment *env = nullptr; IScriptEnvironment *env = nullptr;
std::mutex AviSynthMutex; std::mutex AviSynthMutex;
} }
@ -54,14 +68,26 @@ typedef IScriptEnvironment* __stdcall FUNC(int);
AviSynthWrapper::AviSynthWrapper() { AviSynthWrapper::AviSynthWrapper() {
if (!avs_refcount++) { 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) 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) 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); env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION);
@ -79,9 +105,13 @@ AviSynthWrapper::AviSynthWrapper() {
AviSynthWrapper::~AviSynthWrapper() { AviSynthWrapper::~AviSynthWrapper() {
if (!--avs_refcount) { if (!--avs_refcount) {
delete env; env->DeleteScriptEnvironment();
AVS_linkage = nullptr; #ifdef _WIN32
FreeLibrary(hLib); FreeLibrary(hLib);
#else
dlclose(hLib);
#endif
AVS_linkage = nullptr;
} }
} }

View File

@ -339,7 +339,7 @@
} }
}, },
"Avisynth" : { "Avisynth" : {
"Memory Max" : 128 "Memory Max" : 1024
}, },
"FFmpegSource" : { "FFmpegSource" : {
"Cache" : { "Cache" : {

View File

@ -338,7 +338,7 @@
} }
}, },
"Avisynth" : { "Avisynth" : {
"Memory Max" : 128 "Memory Max" : 1024
}, },
"FFmpegSource" : { "FFmpegSource" : {
"Cache" : { "Cache" : {

View File

@ -174,11 +174,8 @@ if host_machine.system() == 'darwin'
) )
elif host_machine.system() == 'windows' elif host_machine.system() == 'windows'
aegisub_src += files( aegisub_src += files(
'avisynth_wrap.cpp',
'font_file_lister_gdi.cpp', 'font_file_lister_gdi.cpp',
# 'libass_gdi_fontselect.cpp', # 'libass_gdi_fontselect.cpp',
'audio_provider_avs.cpp',
'video_provider_avs.cpp',
) )
if cc.has_header('wingdi.h') if cc.has_header('wingdi.h')
@ -241,6 +238,10 @@ opt_src = [
'video_provider_ffmpegsource.cpp', 'video_provider_ffmpegsource.cpp',
'ffmpegsource_common.cpp']], 'ffmpegsource_common.cpp']],
['AviSynth', ['avisynth_wrap.cpp',
'audio_provider_avs.cpp',
'video_provider_avs.cpp']],
['Hunspell', 'spellchecker_hunspell.cpp'], ['Hunspell', 'spellchecker_hunspell.cpp'],
] ]

View File

@ -399,8 +399,8 @@ void Advanced_Audio(wxTreebook *book, Preferences *parent) {
#ifdef WITH_AVISYNTH #ifdef WITH_AVISYNTH
auto avisynth = p->PageSizer("Avisynth"); auto avisynth = p->PageSizer("Avisynth");
const wxString adm_arr[3] = { "ConvertToMono", "GetLeftChannel", "GetRightChannel" }; const wxString adm_arr[4] = { "None", "ConvertToMono", "GetLeftChannel", "GetRightChannel" };
wxArrayString adm_choice(3, adm_arr); wxArrayString adm_choice(4, adm_arr);
p->OptionChoice(avisynth, _("Avisynth down-mixer"), adm_choice, "Audio/Downmixer"); p->OptionChoice(avisynth, _("Avisynth down-mixer"), adm_choice, "Audio/Downmixer");
p->OptionAdd(avisynth, _("Force sample rate"), "Provider/Audio/AVS/Sample Rate"); p->OptionAdd(avisynth, _("Force sample rate"), "Provider/Audio/AVS/Sample Rate");
#endif #endif

View File

@ -93,7 +93,7 @@ public:
bool HasAudio() const override { return has_audio; } 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); agi::acs::CheckFileRead(filename);
std::lock_guard<std::mutex> lock(avs.GetMutex()); std::lock_guard<std::mutex> lock(avs.GetMutex());
@ -182,6 +182,9 @@ file_exit:
throw VideoOpenError("Avisynth error: " + std::string(err.msg)); 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) { void AvisynthVideoProvider::Init(std::string const& colormatrix) {
auto script = source_clip; auto script = source_clip;