/// @brief Constructor /// @param _filename /// AvisynthAudioProvider::AvisynthAudioProvider(wxString filename) : filename(filename) { try { AVSValue script; wxMutexLocker lock(avs_wrapper.GetMutex()); wxFileName fn(filename); if (!fn.FileExists()) throw agi::FileNotFoundError(STD_STR(filename)); IScriptEnvironment *env = avs_wrapper.GetEnv(); // Include if (filename.EndsWith(".avs")) { char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal)); script = env->Invoke("Import", fname); } // Use DirectShowSource else { const char * argnames[3] = { 0, "video", "audio" }; AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true }; // Load DirectShowSource.dll from app dir if it exists wxFileName dsspath(StandardPaths::DecodePath("?data/DirectShowSource.dll")); if (dsspath.FileExists()) { env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal))); } // Load audio with DSS if it exists if (env->FunctionExists("DirectShowSource")) { script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames); } // Otherwise fail else { throw agi::AudioProviderOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.", 0); } } LoadFromClip(script); } catch (AvisynthError &err) { std::string errmsg(err.msg); if (errmsg.find("filter graph manager won't talk to me") != errmsg.npos) throw agi::AudioDataNotFoundError("Avisynth error: " + errmsg, 0); else throw agi::AudioProviderOpenError("Avisynth error: " + errmsg, 0); } }
AVSValue AvisynthVideoProvider::Open(agi::fs::path const& filename) { IScriptEnvironment *env = avs.GetEnv(); char *videoFilename = env->SaveString(agi::fs::ShortName(filename).c_str()); // Avisynth file, just import it if (agi::fs::HasExtension(filename, "avs")) { LOG_I("avisynth/video") << "Opening .avs file with Import"; decoder_name = "Avisynth/Import"; return env->Invoke("Import", videoFilename); } // Open avi file with AviSource if (agi::fs::HasExtension(filename, "avi")) { LOG_I("avisynth/video") << "Opening .avi file with AviSource"; try { const char *argnames[2] = { 0, "audio" }; AVSValue args[2] = { videoFilename, false }; decoder_name = "Avisynth/AviSource"; return env->Invoke("AviSource", AVSValue(args,2), argnames); } // On Failure, fallback to DSS catch (AvisynthError &err) { LOG_E("avisynth/video") << err.msg; LOG_I("avisynth/video") << "Failed to open .avi file with AviSource, trying DirectShowSource"; } } // Open d2v with mpeg2dec3 if (agi::fs::HasExtension(filename, "d2v") && env->FunctionExists("Mpeg2Dec3_Mpeg2Source")) { LOG_I("avisynth/video") << "Opening .d2v file with Mpeg2Dec3_Mpeg2Source"; auto script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename); decoder_name = "Avisynth/Mpeg2Dec3_Mpeg2Source"; //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this if (env->FunctionExists("SetPlanarLegacyAlignment")) { AVSValue args[2] = { script, true }; script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2)); } return script; } // If that fails, try opening it with DGDecode if (agi::fs::HasExtension(filename, "d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) { LOG_I("avisynth/video") << "Opening .d2v file with DGDecode_Mpeg2Source"; decoder_name = "DGDecode_Mpeg2Source"; return env->Invoke("Avisynth/Mpeg2Source", videoFilename); //note that DGDecode will also have issues like if the version is too // ancient but no sane person would use that anyway } if (agi::fs::HasExtension(filename, "d2v") && env->FunctionExists("Mpeg2Source")) { LOG_I("avisynth/video") << "Opening .d2v file with other Mpeg2Source"; AVSValue script = env->Invoke("Mpeg2Source", videoFilename); decoder_name = "Avisynth/Mpeg2Source"; //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this if (env->FunctionExists("SetPlanarLegacyAlignment")) script = env->Invoke("SetPlanarLegacyAlignment", script); return script; } // Try loading DirectShowSource2 if (!env->FunctionExists("dss2")) { auto dss2path(config::path->Decode("?data/avss.dll")); if (agi::fs::FileExists(dss2path)) env->Invoke("LoadPlugin", env->SaveString(agi::fs::ShortName(dss2path).c_str())); } // If DSS2 loaded properly, try using it if (env->FunctionExists("dss2")) { LOG_I("avisynth/video") << "Opening file with DSS2"; decoder_name = "Avisynth/DSS2"; return env->Invoke("DSS2", videoFilename); } // Try DirectShowSource // Load DirectShowSource.dll from app dir if it exists auto dsspath(config::path->Decode("?data/DirectShowSource.dll")); if (agi::fs::FileExists(dsspath)) env->Invoke("LoadPlugin", env->SaveString(agi::fs::ShortName(dsspath).c_str())); // Then try using DSS if (env->FunctionExists("DirectShowSource")) { const char *argnames[3] = { 0, "video", "audio" }; AVSValue args[3] = { videoFilename, true, false }; decoder_name = "Avisynth/DirectShowSource"; warning = "Warning! The file is being opened using Avisynth's DirectShowSource, which has unreliable seeking. Frame numbers might not match the real number. PROCEED AT YOUR OWN RISK!"; LOG_I("avisynth/video") << "Opening file with DirectShowSource"; return env->Invoke("DirectShowSource", AVSValue(args,3), argnames); } // Failed to find a suitable function LOG_E("avisynth/video") << "DSS function not found"; throw VideoNotSupported("No function suitable for opening the video found"); }