This commit is contained in:
n00mkrad
2022-06-04 12:43:48 +02:00
parent 2a3fe9a88f
commit eb174ade38
8 changed files with 92 additions and 44 deletions

View File

@@ -22,7 +22,7 @@ namespace Flowframes.Data
public static AI xvfiCuda = new AI(AI.AiBackend.Pytorch, "XVFI_CUDA", "XVFI",
"CUDA/Pytorch Implementation of XVFI (Nvidia Only!)", "xvfi-cuda", AI.InterpFactorSupport.AnyInteger, new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10 });
public static List<AI> networks = new List<AI> { rifeCuda, rifeNcnn, rifeNcnnVs, flavrCuda, dainNcnn, xvfiCuda };
public static List<AI> networks = new List<AI> { rifeCuda, rifeNcnnVs, rifeNcnn, flavrCuda, dainNcnn, xvfiCuda };
public static AI GetAi (string aiName)
{

32
Code/Form1.Designer.cs generated
View File

@@ -95,7 +95,7 @@
this.completionAction = new System.Windows.Forms.ComboBox();
this.label25 = new System.Windows.Forms.Label();
this.encodingSettingsBtn = new HTAlt.WinForms.HTButton();
this.scnDetectTestBtn = new HTAlt.WinForms.HTButton();
this.realtimeBtn = new HTAlt.WinForms.HTButton();
this.inputInfo = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.browseOutBtn = new HTAlt.WinForms.HTButton();
@@ -918,7 +918,7 @@
this.interpOptsTab.Controls.Add(this.outSpeedCombox);
this.interpOptsTab.Controls.Add(this.completionActionPanel);
this.interpOptsTab.Controls.Add(this.encodingSettingsBtn);
this.interpOptsTab.Controls.Add(this.scnDetectTestBtn);
this.interpOptsTab.Controls.Add(this.realtimeBtn);
this.interpOptsTab.Controls.Add(this.inputInfo);
this.interpOptsTab.Controls.Add(this.label1);
this.interpOptsTab.Controls.Add(this.browseOutBtn);
@@ -1026,20 +1026,20 @@
this.encodingSettingsBtn.UseVisualStyleBackColor = false;
this.encodingSettingsBtn.Click += new System.EventHandler(this.encodingSettingsBtn_Click);
//
// scnDetectTestBtn
// realtimeBtn
//
this.scnDetectTestBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.scnDetectTestBtn.FlatAppearance.BorderSize = 0;
this.scnDetectTestBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.scnDetectTestBtn.ForeColor = System.Drawing.Color.White;
this.scnDetectTestBtn.Location = new System.Drawing.Point(689, 185);
this.scnDetectTestBtn.Name = "scnDetectTestBtn";
this.scnDetectTestBtn.Size = new System.Drawing.Size(206, 23);
this.scnDetectTestBtn.TabIndex = 38;
this.scnDetectTestBtn.Text = "Scn Detect Test";
this.scnDetectTestBtn.UseVisualStyleBackColor = false;
this.scnDetectTestBtn.Visible = false;
this.scnDetectTestBtn.Click += new System.EventHandler(this.scnDetectTestBtn_Click);
this.realtimeBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.realtimeBtn.FlatAppearance.BorderSize = 0;
this.realtimeBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.realtimeBtn.ForeColor = System.Drawing.Color.White;
this.realtimeBtn.Location = new System.Drawing.Point(689, 185);
this.realtimeBtn.Name = "realtimeBtn";
this.realtimeBtn.Size = new System.Drawing.Size(206, 23);
this.realtimeBtn.TabIndex = 38;
this.realtimeBtn.Text = "Realtime Interpolation";
this.realtimeBtn.UseVisualStyleBackColor = false;
this.realtimeBtn.Visible = false;
this.realtimeBtn.Click += new System.EventHandler(this.scnDetectTestBtn_Click);
//
// inputInfo
//
@@ -1808,7 +1808,7 @@
private System.Windows.Forms.Panel mpDedupePanel;
private System.Windows.Forms.ComboBox mpdecimateMode;
private System.Windows.Forms.LinkLabel linkLabel1;
private HTAlt.WinForms.HTButton scnDetectTestBtn;
private HTAlt.WinForms.HTButton realtimeBtn;
private System.Windows.Forms.Panel busyControlsPanel;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Button pauseBtn;

View File

@@ -17,6 +17,7 @@ using Flowframes.MiscUtils;
using System.Threading.Tasks;
using System.Linq;
using System.Runtime.InteropServices;
using Flowframes.Media;
#pragma warning disable IDE1006
@@ -72,7 +73,7 @@ namespace Flowframes
if (Debugger.IsAttached)
{
Logger.Log("Debugger is attached - Flowframes seems to be running within VS.");
scnDetectTestBtn.Visible = true;
realtimeBtn.Visible = true;
}
completionAction.SelectedIndex = 0;
@@ -278,9 +279,8 @@ namespace Flowframes
Logger.Log($"AI implementation {ai.FriendlyName} ({ai.Backend}) has not been loaded because Pytorch was not found.", true);
continue;
}
aiCombox.Items.Add(ai.FriendlyName + " - " + ai.Description);
aiCombox.Items.Add(GetAiComboboxName(ai));
}
string lastUsedAiName = Config.Get(Config.Key.lastUsedAiName);
@@ -291,6 +291,11 @@ namespace Flowframes
ConfigParser.LoadComboxIndex(outModeCombox);
}
private string GetAiComboboxName (AI ai)
{
return ai.FriendlyName + " - " + ai.Description;
}
public void Initialized()
{
initialized = true;
@@ -376,7 +381,16 @@ namespace Flowframes
public AI GetAi()
{
return Implementations.networks[aiCombox.SelectedIndex];
foreach(AI ai in Implementations.networks)
{
if (GetAiComboboxName(ai) == aiCombox.Text)
return ai;
}
Logger.Log($"AI implementation lookup failed! This should not happen! Please tell tehe developer!");
return Implementations.networks[0];
//return Implementations.networks[aiCombox.SelectedIndex];
}
void inputTbox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
@@ -703,9 +717,16 @@ namespace Flowframes
#endregion
private void scnDetectTestBtn_Click(object sender, EventArgs e)
private async void scnDetectTestBtn_Click(object sender, EventArgs e)
{
Magick.SceneDetect.RunSceneDetection(inputTbox.Text.Trim());
if (BatchProcessing.busy || !File.Exists(inputTbox.Text.Trim())) return;
Interpolate.current = GetCurrentSettings();
Interpolate.currentInputFrameCount = await GetFrameCountCached.GetFrameCountAsync(Interpolate.current.inPath);
AiProcessSuspend.Reset();
await Interpolate.Realtime();
SetProgress(0);
}
private void pauseBtn_Click(object sender, EventArgs e)

View File

@@ -756,6 +756,9 @@ namespace Flowframes.IO
public static bool CreateDir (string path) // Returns whether the dir already existed
{
if (string.IsNullOrWhiteSpace(path))
return false;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);

View File

@@ -106,15 +106,13 @@ namespace Flowframes.Main
if (Config.GetBool(Config.Key.fixOutputDuration)) // Match input duration by padding duping last frame until interp frames == (inputframes * factor)
{
int neededFrames = (frameFiles.Length * interpFactor).RoundToInt() - fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Count();
for (int i = 0; i < neededFrames; i++)
fileContent += fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Last();
}
if (loop)
{
fileContent = fileContent.Remove(fileContent.LastIndexOf("\n"));
}
File.WriteAllText(framesFile, fileContent);
File.WriteAllText(framesFile + ".inputframes.json", JsonConvert.SerializeObject(inputFilenames, Formatting.Indented));

View File

@@ -88,6 +88,11 @@ namespace Flowframes
Program.mainForm.InterpolationDone();
}
public static async Task Realtime ()
{
await AiProcess.RunRifeNcnnVs(current.framesFolder, "", current.interpFactor, current.model.dir, true);
}
public static async Task<int> GetCurrentInputFrameCount()
{
if (currentInputFrameCount < 2)

View File

@@ -318,7 +318,7 @@ namespace Flowframes.Os
while (!rifeNcnn.HasExited) await Task.Delay(1);
}
public static async Task RunRifeNcnnVs(string framesPath, string outPath, float factor, string mdl)
public static async Task RunRifeNcnnVs(string framesPath, string outPath, float factor, string mdl, bool rt = false)
{
processTimeMulti.Restart();
@@ -327,7 +327,7 @@ namespace Flowframes.Os
bool uhd = await InterpolateUtils.UseUhd();
Logger.Log($"Running RIFE (NCNN-VS){(uhd ? " (UHD Mode)" : "")}...", false);
await RunRifeNcnnVsProcess(framesPath, factor, outPath, mdl, uhd);
await RunRifeNcnnVsProcess(framesPath, factor, outPath, mdl, uhd, rt);
}
catch (Exception e)
{
@@ -338,27 +338,31 @@ namespace Flowframes.Os
await AiFinished("RIFE");
}
static async Task RunRifeNcnnVsProcess(string inPath, float factor, string outPath, string mdl, bool uhd)
static async Task RunRifeNcnnVsProcess(string inPath, float factor, string outPath, string mdl, bool uhd, bool rt = false)
{
Directory.CreateDirectory(outPath);
IoUtils.CreateDir(outPath);
string logFileName = "rife-ncnn-vs-log";
Process rifeNcnnVs = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd());
AiStarted(rifeNcnnVs, 1500, inPath);
SetProgressCheck(Interpolate.currentInputFrameCount, factor, logFileName);
if(!rt)
SetProgressCheck(Interpolate.currentInputFrameCount, factor, logFileName);
string avDir = Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir);
string rtArgs = $"-window_title \"Flowframes Realtime Interpolation ({Interpolate.current.inFps.GetString()} FPS x{factor} = {Interpolate.current.outFps.GetString()} FPS - {mdl})\" -autoexit -seek_interval 20 " +
$"-vf \"drawtext=fontfile='C\\:/WINDOWS/fonts/consola.ttf':text='%{{pts\\:hms}}':x=-7:y=1:fontcolor=white:fontsize=15\"";
Interpolate.current.FullOutPath = Path.Combine(Interpolate.current.outPath, await IoUtils.GetCurrentExportFilename(false, true));
string encArgs = FfmpegUtils.GetEncArgs(FfmpegUtils.GetCodec(Interpolate.current.outMode), (Interpolate.current.ScaledResolution.IsEmpty ? Interpolate.current.InputResolution : Interpolate.current.ScaledResolution), Interpolate.current.outFps.GetFloat()).FirstOrDefault();
string ffmpegArgs = $"ffmpeg -y -i pipe: {encArgs} {Interpolate.current.FullOutPath.Wrap()}";
string ffmpegArgs = rt ? $"{Path.Combine(avDir, "ffplay").Wrap()} {rtArgs} - " : $"{Path.Combine(avDir, "ffmpeg").Wrap()} -y -i pipe: {encArgs} {Interpolate.current.FullOutPath.Wrap()}";
float scn = Config.GetBool(Config.Key.scnDetect) ? Config.GetFloat(Config.Key.scnDetectValue) : 0f;
Size res = InterpolateUtils.GetOutputResolution(Interpolate.current.InputResolution, true, true);
string pkgDir = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir);
string vsModelDir = Path.Combine(pkgDir, "vapoursynth64", "plugins", "models", mdl);
IoUtils.CopyDir(Path.Combine(pkgDir, mdl), vsModelDir);
VapourSynthUtils.VsSettings vsSettings = new VapourSynthUtils.VsSettings()
{ InterpSettings = Interpolate.current, ModelDir = mdl, Factor = factor, Res = res, Uhd = uhd, SceneDetectSensitivity = scn, Loop = Config.GetBool(Config.Key.enableLoop), MatchDuration = Config.GetBool(Config.Key.fixOutputDuration) };
{ InterpSettings = Interpolate.current, ModelDir = mdl, Factor = factor, Res = res, Uhd = uhd, SceneDetectSensitivity = scn, Loop = Config.GetBool(Config.Key.enableLoop), MatchDuration = Config.GetBool(Config.Key.fixOutputDuration), Realtime = rt };
rifeNcnnVs.StartInfo.Arguments = $"{OsUtils.GetCmdArg()} cd /D {pkgDir.Wrap()} & vspipe {VapourSynthUtils.CreateScript(vsSettings).Wrap()} -c y4m - | {ffmpegArgs}";
@@ -379,10 +383,6 @@ namespace Flowframes.Os
}
while (!rifeNcnnVs.HasExited) await Task.Delay(1);
await Task.Delay(100);
IoUtils.TryDeleteIfExists(vsModelDir);
}
public static async Task RunDainNcnn(string framesPath, string outPath, float factor, string mdl, int tilesize)
@@ -514,6 +514,15 @@ namespace Flowframes.Os
if (line.Contains("ff:nocuda-cpu"))
Logger.Log("WARNING: CUDA-capable GPU device is not available, running on CPU instead!");
if(true /* if NCNN VS */)
{
if (!hasShownError && line.ToLower().Contains("allocate memory failed"))
{
hasShownError = true;
UiUtils.ShowMessageBox($"Out of memory!\nTry reducing your RAM usage by closing some programs.\n\n{line}", UiUtils.MessageType.Error);
}
}
if (!hasShownError && err && line.ToLower().Contains("out of memory"))
{
hasShownError = true;

View File

@@ -25,18 +25,21 @@ namespace Flowframes.Os
public bool Tta { get; set; } = false;
public bool Loop { get; set; } = false;
public bool MatchDuration { get; set; } = false;
public bool Realtime { get; set; } = false;
}
public static string CreateScript(VsSettings s)
{
string inputPath = s.InterpSettings.inPath;
string mdlPath = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir, s.ModelDir).Replace(@"\", "/").Wrap();
bool sc = s.SceneDetectSensitivity >= 0.01f;
int endDupeCount = s.Factor.RoundToInt() - 1;
int targetFrameCountMatchDuration = (Interpolate.currentInputFrameCount * s.Factor).RoundToInt(); // Target frame count to match original duration (and for loops)
int targetFrameCountTrue = targetFrameCountMatchDuration - endDupeCount; // Target frame count without dupes at the end (only in-between frames added)
List<string> l = new List<string> { "import sys", "import vapoursynth as vs", "core = vs.core" }; // Imports
List<string> l = new List<string> { "import sys", "import os", "import vapoursynth as vs", "core = vs.core", "" }; // Imports
if (s.InterpSettings.inputIsFrames)
{
@@ -46,7 +49,10 @@ namespace Flowframes.Os
}
else
{
l.Add($"clip = core.lsmas.LWLibavSource(r'{inputPath}', cachefile=r'{Path.Combine(s.InterpSettings.tempFolder, "lsmash.cache.lwi")}')"); // Load video with lsmash
l.Add($"indexFilePath = r'{inputPath}.cache.lwi'");
l.Add($"if os.path.isdir(r'{s.InterpSettings.tempFolder}'):");
l.Add($"\tindexFilePath = r'{Path.Combine(s.InterpSettings.tempFolder, "cache.lwi")}'");
l.Add($"clip = core.lsmas.LWLibavSource(r'{inputPath}', cachefile=indexFilePath)"); // Load video with lsmash
}
if (s.Loop && !s.InterpSettings.inputIsFrames)
@@ -60,21 +66,27 @@ namespace Flowframes.Os
if (sc)
l.Add($"clip = core.misc.SCDetect(clip=clip,threshold={s.SceneDetectSensitivity.ToStringDot()})"); // Scene detection
l.Add($"clip = core.rife.RIFE(clip, {9}, {s.Factor.ToStringDot()}, {s.GpuId}, {s.GpuThreads}, {s.Tta}, {s.Uhd}, {sc})"); // Interpolate
l.Add($"clip = core.rife.RIFE(clip, {9}, {s.Factor.ToStringDot()}, {mdlPath}, {s.GpuId}, {s.GpuThreads}, {s.Tta}, {s.Uhd}, {sc})"); // Interpolate
l.Add($"clip = vs.core.resize.Bicubic(clip, format=vs.YUV444P16, matrix_s=\"709\")"); // Convert RGB to YUV
if (s.Loop)
{
l.Add($"clip = clip.std.Trim(0, {targetFrameCountMatchDuration}-1)");
l.Add($"clip = clip.std.Trim(0, {targetFrameCountMatchDuration - 1})"); // -1 because we use index, not count
}
else
{
if (!s.MatchDuration)
l.Add($"clip = clip.std.Trim(0, {targetFrameCountTrue}-1)");
l.Add($"clip = clip.std.Trim(0, {targetFrameCountTrue - 1})"); // -1 because we use index, not count
}
if(s.Realtime && s.Loop)
l.Add($"clip = clip.std.Loop(0)"); // Can't loop piped video so we loop it before piping it to ffplay
l.Add($"clip.set_output()"); // Set output
l.Add($"if os.path.isfile(r'{inputPath}.cache.lwi'):");
l.Add($"\tos.remove(r'{inputPath}.cache.lwi')");
string pkgPath = Path.Combine(Paths.GetPkgPath(), Implementations.rifeNcnnVs.PkgDir);
string vpyPath = Path.Combine(pkgPath, "rife.vpy");