Example #1
0
/// @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");
}