diff --git a/Code/Data/Paths.cs b/Code/Data/Paths.cs
index 8218730..febc205 100644
--- a/Code/Data/Paths.cs
+++ b/Code/Data/Paths.cs
@@ -9,6 +9,7 @@ namespace Flowframes.IO
public const string framesDir = "frames";
public const string interpDir = "interp";
public const string chunksDir = "vchunks";
+ public const string resumeDir = "resumedata";
public const string scenesDir = "scenes";
public const string alphaSuffix = "-a";
diff --git a/Code/Data/ResumeState.cs b/Code/Data/ResumeState.cs
new file mode 100644
index 0000000..1f3e8b2
--- /dev/null
+++ b/Code/Data/ResumeState.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Flowframes.Data
+{
+ public struct ResumeState
+ {
+ bool autoEncode;
+ int lastInterpolatedInputFrame;
+
+ public ResumeState (bool autoEncArg, int lastInterpInFrameArg)
+ {
+ autoEncode = autoEncArg;
+ lastInterpolatedInputFrame = lastInterpInFrameArg;
+ }
+
+ public override string ToString ()
+ {
+ string s = $"AUTOENC|{autoEncode}";
+
+ if (!autoEncode)
+ {
+ s += $"\nLASTINPUTFRAME|{lastInterpolatedInputFrame}";
+ }
+
+ return s;
+ }
+ }
+}
diff --git a/Code/Flowframes.csproj b/Code/Flowframes.csproj
index 4866c33..aa7fcc7 100644
--- a/Code/Flowframes.csproj
+++ b/Code/Flowframes.csproj
@@ -205,6 +205,7 @@
+
Form
@@ -241,6 +242,7 @@
+
diff --git a/Code/IO/IOUtils.cs b/Code/IO/IOUtils.cs
index 6d29303..35c8654 100644
--- a/Code/IO/IOUtils.cs
+++ b/Code/IO/IOUtils.cs
@@ -280,11 +280,16 @@ namespace Flowframes.IO
return oldNewNamesMap;
}
- public static void ReverseRenaming(Dictionary oldNewMap, bool clearDict)
+ public static async Task ReverseRenaming(Dictionary oldNewMap, bool clearDict)
{
if (oldNewMap == null || oldNewMap.Count < 1) return;
+ int counter = 0;
foreach (KeyValuePair pair in oldNewMap)
+ {
TryMove(pair.Value, pair.Key);
+ if (counter % 1000 == 0)
+ await Task.Delay(1);
+ }
if (clearDict)
oldNewMap.Clear();
}
diff --git a/Code/Main/AutoEncode.cs b/Code/Main/AutoEncode.cs
index 2f6fc2d..6ed420a 100644
--- a/Code/Main/AutoEncode.cs
+++ b/Code/Main/AutoEncode.cs
@@ -117,7 +117,7 @@ namespace Flowframes.Main
if (Interpolate.canceled) return;
- IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
+ await IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outFilename);
}
catch (Exception e)
diff --git a/Code/Main/Interpolate.cs b/Code/Main/Interpolate.cs
index 00a7470..ed306db 100644
--- a/Code/Main/Interpolate.cs
+++ b/Code/Main/Interpolate.cs
@@ -25,11 +25,8 @@ namespace Flowframes
public static int currentInputFrameCount;
public static bool currentlyUsingAutoEnc;
-
public static InterpSettings current;
-
public static bool canceled = false;
-
static Stopwatch sw = new Stopwatch();
public static async Task Start()
@@ -54,7 +51,7 @@ namespace Flowframes
Program.mainForm.SetProgress(100);
if(!currentlyUsingAutoEnc)
await CreateVideo.Export(current.interpFolder, current.outFilename, current.outMode, false);
- IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
+ await IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
await Cleanup();
Program.mainForm.SetWorking(false);
Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed));
diff --git a/Code/Main/InterpolateSteps.cs b/Code/Main/InterpolateSteps.cs
index 921233e..65c6b72 100644
--- a/Code/Main/InterpolateSteps.cs
+++ b/Code/Main/InterpolateSteps.cs
@@ -98,7 +98,7 @@ namespace Flowframes.Main
currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath);
- IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
+ await IOUtils.ReverseRenaming(AiProcess.filenameMap, true); // Get timestamps back
// TODO: Check if this works lol, remove if it does
//if (Config.GetBool("sbsAllowAutoEnc"))
diff --git a/Code/Main/InterpolateUtils.cs b/Code/Main/InterpolateUtils.cs
index 552b874..c2a9b66 100644
--- a/Code/Main/InterpolateUtils.cs
+++ b/Code/Main/InterpolateUtils.cs
@@ -98,7 +98,8 @@ namespace Flowframes.Main
public static void UpdateInterpProgress(int frames, int target, string latestFramePath = "")
{
if (i.canceled) return;
-
+ ResumeUtils.currentOutFrames = frames;
+ ResumeUtils.Save();
frames = frames.Clamp(0, target);
int percent = (int)Math.Round(((float)frames / target) * 100f);
Program.mainForm.SetProgress(percent);
diff --git a/Code/Main/ResumeUtils.cs b/Code/Main/ResumeUtils.cs
new file mode 100644
index 0000000..0c5172b
--- /dev/null
+++ b/Code/Main/ResumeUtils.cs
@@ -0,0 +1,83 @@
+using Flowframes.Data;
+using Flowframes.IO;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Flowframes.Main
+{
+
+ class ResumeUtils
+ {
+ public static float timeBetweenSaves = 10;
+ public static int minFrames = 100;
+ public static int safetyDelayFrames = 100;
+ public static string resumeFileName = "resume.ini";
+ public static string filenameMapFileName = "frameFilenames.ini";
+
+ public static int currentOutFrames;
+ public static Stopwatch timeSinceLastSave = new Stopwatch();
+
+ public static void Save ()
+ {
+ if (timeSinceLastSave.IsRunning && timeSinceLastSave.ElapsedMilliseconds < (timeBetweenSaves * 1000f).RoundToInt()) return;
+ timeSinceLastSave.Restart();
+ Directory.CreateDirectory(Path.Combine(Interpolate.current.tempFolder, Paths.resumeDir));
+ SaveState();
+ }
+
+ public static async Task SaveState ()
+ {
+ int frames = GetSafeInterpolatedInputFramesAmount();
+ if (frames < 1) return;
+ ResumeState state = new ResumeState(Interpolate.currentlyUsingAutoEnc, frames);
+ string stateFilePath = Path.Combine(Interpolate.current.tempFolder, Paths.resumeDir, resumeFileName);
+ File.WriteAllText(stateFilePath, state.ToString());
+ await SaveFilenameMap();
+ }
+
+ public static int GetSafeInterpolatedInputFramesAmount()
+ {
+ return (int)Math.Round((float)currentOutFrames / Interpolate.current.interpFactor) - safetyDelayFrames;
+ }
+
+ static async Task SaveFilenameMap ()
+ {
+ string filePath = Path.Combine(Interpolate.current.tempFolder, Paths.resumeDir, filenameMapFileName);
+
+ if (File.Exists(filePath) && IOUtils.GetFilesize(filePath) > 0)
+ return;
+
+ string fileContent = "";
+ int counter = 0;
+
+ foreach (KeyValuePair entry in AiProcess.filenameMap)
+ {
+ if (counter % 500 == 0) await Task.Delay(1);
+ fileContent += $"{entry.Key}|{entry.Value}\n";
+ }
+
+ File.WriteAllText(filePath, fileContent);
+ }
+
+ static void LoadFilenameMap()
+ {
+ Dictionary dict = new Dictionary();
+ string filePath = Path.Combine(Interpolate.current.tempFolder, Paths.resumeDir, filenameMapFileName);
+ string[] dictLines = File.ReadAllLines(filePath);
+
+ foreach (string line in dictLines)
+ {
+ if (line.Length < 5) continue;
+ string[] keyValuePair = line.Split('|');
+ dict.Add(keyValuePair[0].Trim(), keyValuePair[1].Trim());
+ }
+
+ AiProcess.filenameMap = dict;
+ }
+ }
+}