Files
flowframes/Code/Main/FrameOrder.cs

207 lines
9.6 KiB
C#
Raw Normal View History

2020-12-02 17:23:24 +01:00
using Flowframes.Data;
using Flowframes.IO;
2021-02-16 11:27:00 +01:00
using Flowframes.MiscUtils;
using Flowframes.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Flowframes.Main
{
class FrameOrder
{
static Stopwatch benchmark = new Stopwatch();
2021-02-16 11:27:00 +01:00
static FileInfo[] frameFiles;
static FileInfo[] frameFilesWithoutLast;
static List<string> sceneFrames = new List<string>();
static string currentFormat = "D8";
static Dictionary<int, string> frameFileContents = new Dictionary<int, string>();
static int lastOutFileCount = 0;
2020-12-29 16:01:24 +01:00
public static async Task CreateFrameOrderFile(string framesPath, bool loopEnabled, float times)
{
Logger.Log("Generating frame order information...");
try
{
foreach (FileInfo file in IOUtils.GetFileInfosSorted(framesPath.GetParentDir(), false, $"{Paths.frameOrderPrefix}*.*"))
file.Delete();
benchmark.Restart();
2021-02-16 11:27:00 +01:00
currentFormat = $"D{Padding.interpFrames}";
2021-01-21 09:40:11 +01:00
await CreateEncFile(framesPath, loopEnabled, times, false);
Logger.Log($"Generating frame order information... Done.", false, true);
Logger.Log($"Generated frame order info file in {benchmark.ElapsedMilliseconds} ms", true);
}
catch (Exception e)
{
Logger.Log($"Error generating frame order information: {e.Message}");
}
}
static Dictionary<string, int> dupesDict = new Dictionary<string, int>();
static void LoadDupesFile(string path)
{
dupesDict.Clear();
if (!File.Exists(path)) return;
string[] dupesFileLines = IOUtils.ReadLines(path);
foreach (string line in dupesFileLines)
{
string[] values = line.Split(':');
dupesDict.Add(values[0], values[1].GetInt());
}
}
public static async Task CreateEncFile(string framesPath, bool loopEnabled, float interpFactor, bool notFirstRun)
{
if (Interpolate.canceled) return;
Logger.Log($"Generating frame order information for {interpFactor}x...", false, true);
bool loop = Config.GetBool("enableLoop");
bool sceneDetection = true;
string ext = InterpolateUtils.GetOutExt();
2021-02-16 11:27:00 +01:00
frameFileContents.Clear();
lastOutFileCount = 0;
frameFiles = new DirectoryInfo(framesPath).GetFiles($"*.png");
frameFilesWithoutLast = frameFiles;
Array.Resize(ref frameFilesWithoutLast, frameFilesWithoutLast.Length - 1);
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(interpFactor));
string fileContent = "";
string dupesFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
LoadDupesFile(dupesFile);
string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir);
2021-02-16 11:27:00 +01:00
sceneFrames.Clear();
2021-02-25 14:57:57 +01:00
if (Directory.Exists(scnFramesPath))
sceneFrames = Directory.GetFiles(scnFramesPath).Select(file => Path.GetFileNameWithoutExtension(file)).ToList();
bool debug = Config.GetBool("frameOrderDebug", false);
int interpFramesAmount = (int)interpFactor; // TODO: This code won't work with fractional factors
2021-02-16 11:27:00 +01:00
List<Task> tasks = new List<Task>();
int linesPerTask = 400 / (int)interpFactor;
int num = 0;
for (int i = 0; i < frameFilesWithoutLast.Length; i += linesPerTask)
2021-02-16 11:27:00 +01:00
{
tasks.Add(GenerateFrameLines(num, i, linesPerTask, (int)interpFactor, loopEnabled, sceneDetection, debug));
num++;
}
await Task.WhenAll(tasks);
for (int x = 0; x < frameFileContents.Count; x++)
fileContent += frameFileContents[x];
lastOutFileCount++;
fileContent += $"file '{Paths.interpDir}/{lastOutFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'"; // Last frame (source)
if (loop)
2021-02-16 11:27:00 +01:00
fileContent = fileContent.Remove(fileContent.LastIndexOf("\n"));
File.WriteAllText(vfrFile, fileContent);
if (notFirstRun) return; // Skip all steps that only need to be done once
if (loop)
{
int lastFileNumber = frameFiles.Last().Name.GetInt() + 1;
string loopFrameTargetPath = Path.Combine(frameFilesWithoutLast.First().FullName.GetParentDir(), lastFileNumber.ToString().PadLeft(Padding.inputFrames, '0') + $".png");
if (File.Exists(loopFrameTargetPath))
{
if (debug) Logger.Log($"Won't copy loop frame - {Path.GetFileName(loopFrameTargetPath)} already exists.", true);
return;
}
File.Copy(frameFilesWithoutLast.First().FullName, loopFrameTargetPath);
if (debug) Logger.Log($"Copied loop frame to {loopFrameTargetPath}.", true);
}
}
static async Task GenerateFrameLines(int number, int startIndex, int count, int factor, bool loopEnabled, bool sceneDetection, bool debug)
2021-02-16 11:27:00 +01:00
{
int totalFileCount = (startIndex) * factor;
int interpFramesAmount = factor;
string ext = InterpolateUtils.GetOutExt();
string fileContent = "";
2021-02-16 11:27:00 +01:00
for (int i = startIndex; i < (startIndex + count); i++)
{
if (Interpolate.canceled) return;
2021-02-16 11:27:00 +01:00
if (i >= frameFilesWithoutLast.Length) break;
2021-03-14 20:34:35 +01:00
// if (debug && i == startIndex)
// fileContent += $"# NEW THREAD - {startIndex} to {startIndex + count}\n";
2021-03-01 17:34:47 +01:00
2021-02-16 11:27:00 +01:00
string inputFilenameNoExt = Path.GetFileNameWithoutExtension(frameFilesWithoutLast[i].Name);
int dupesAmount = dupesDict.ContainsKey(inputFilenameNoExt) ? dupesDict[inputFilenameNoExt] : 0;
bool discardThisFrame = (sceneDetection && i < frameFilesWithoutLast.Length && sceneFrames.Contains(Path.GetFileNameWithoutExtension(frameFiles[i + 1].Name))); // i+2 is in scene detection folder, means i+1 is ugly interp frame
2021-02-16 11:27:00 +01:00
if (loopEnabled && i == (frameFiles.Length - 2)) // If loop is enabled, account for the extra frame for loop continuity
interpFramesAmount = interpFramesAmount * 2;
2021-02-16 11:27:00 +01:00
for (int frm = 0; frm < interpFramesAmount; frm++) // Generate frames file lines
{
if (discardThisFrame) // If frame is scene cut frame
{
string frameBeforeScn = Path.GetFileName((frameFiles[i].Name.GetInt() + 1).ToString().PadLeft(Padding.inputFramesRenamed, '0')) + frameFiles[i].Extension;
string frameAfterScn = Path.GetFileName((frameFiles[i + 1].Name.GetInt() + 1).ToString().PadLeft(Padding.inputFramesRenamed, '0')) + frameFiles[i + 1].Extension;
string scnChangeNote = $"SCN:{frameBeforeScn}>{frameAfterScn}";
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}]", scnChangeNote);
if (Config.GetInt("sceneChangeFillMode") == 0) // Duplicate last frame
{
totalFileCount++;
int lastNum = totalFileCount;
for (int dupeCount = 1; dupeCount < interpFramesAmount; dupeCount++)
{
totalFileCount++;
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, lastNum, ext, debug, $"[In: {inputFilenameNoExt}] [DISCARDED]");
}
}
else
{
totalFileCount++;
for (int dupeCount = 1; dupeCount < interpFramesAmount; dupeCount++)
{
totalFileCount++;
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, ext, debug, $"[In: {inputFilenameNoExt}] [DISCARDED - BLEND]");
}
}
frm = interpFramesAmount;
}
else
{
totalFileCount++;
2021-02-16 11:27:00 +01:00
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}]");
}
}
}
if (totalFileCount > lastOutFileCount)
2021-02-16 11:27:00 +01:00
lastOutFileCount = totalFileCount;
2021-02-16 11:27:00 +01:00
frameFileContents[number] = fileContent;
}
static string WriteFrameWithDupes(int dupesAmount, string fileContent, int frameNum, string ext, bool debug, string debugNote = "", string forcedNote = "")
{
for (int writtenDupes = -1; writtenDupes < dupesAmount; writtenDupes++) // Write duplicates
fileContent += $"file '{Paths.interpDir}/{frameNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}' # {(debug ? ($"Dupe {(writtenDupes + 1).ToString("000")} {debugNote}").Replace("Dupe 000", " ") : "")}{forcedNote}\n";
2021-02-16 11:27:00 +01:00
return fileContent;
}
}
}