2021-08-23 16:50:18 +02:00
|
|
|
|
using Flowframes.Media;
|
|
|
|
|
|
using Flowframes.Data;
|
|
|
|
|
|
using Flowframes.IO;
|
|
|
|
|
|
using Flowframes.Main;
|
|
|
|
|
|
using Flowframes.MiscUtils;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Flowframes
|
|
|
|
|
|
{
|
|
|
|
|
|
public class InterpSettings
|
|
|
|
|
|
{
|
|
|
|
|
|
public string inPath;
|
|
|
|
|
|
public string outPath;
|
2022-05-31 22:17:22 +02:00
|
|
|
|
public string FullOutPath { get; set; } = "";
|
2024-08-21 14:45:46 +02:00
|
|
|
|
public AiInfo ai;
|
2021-08-23 16:50:18 +02:00
|
|
|
|
public Fraction inFps;
|
|
|
|
|
|
public Fraction inFpsDetected;
|
|
|
|
|
|
public Fraction outFps;
|
2024-11-28 16:08:04 +01:00
|
|
|
|
public Fraction outFpsResampled;
|
|
|
|
|
|
public bool FpsResampling => outFpsResampled != null && outFpsResampled.Float > 0.1f && outFpsResampled.Float < outFps.Float;
|
2021-08-28 10:21:52 +02:00
|
|
|
|
public float outItsScale;
|
2021-08-23 16:50:18 +02:00
|
|
|
|
public float interpFactor;
|
2023-01-18 14:55:38 +01:00
|
|
|
|
public OutputSettings outSettings;
|
2021-08-23 16:50:18 +02:00
|
|
|
|
public ModelCollection.ModelInfo model;
|
|
|
|
|
|
|
|
|
|
|
|
public string tempFolder;
|
|
|
|
|
|
public string framesFolder;
|
|
|
|
|
|
public string interpFolder;
|
|
|
|
|
|
public bool inputIsFrames;
|
2024-11-26 13:45:44 +01:00
|
|
|
|
public bool dedupe;
|
2025-02-10 21:03:05 +01:00
|
|
|
|
public bool noRedupe;
|
2021-11-24 21:08:29 +01:00
|
|
|
|
|
2024-11-12 22:13:59 +01:00
|
|
|
|
private Size _inputResolution = new Size();
|
|
|
|
|
|
public Size InputResolution
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_inputResolution.IsEmpty)
|
|
|
|
|
|
_inputResolution = GetMediaResolutionCached.GetSizeAsync(inPath).Result;
|
|
|
|
|
|
return _inputResolution;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Size _outputResolution = new Size();
|
|
|
|
|
|
public Size OutputResolution
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_outputResolution.IsEmpty)
|
|
|
|
|
|
_outputResolution = InterpolateUtils.GetInterpolationResolution(FfmpegCommands.ModuloMode.ForEncoding, InputResolution);
|
|
|
|
|
|
return _outputResolution;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Size _scaledResolution = new Size();
|
|
|
|
|
|
public Size ScaledResolution
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_scaledResolution.IsEmpty)
|
|
|
|
|
|
_scaledResolution = InterpolateUtils.GetInterpolationResolution(FfmpegCommands.ModuloMode.Disabled, InputResolution);
|
|
|
|
|
|
return _scaledResolution;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Size _interpResolution = new Size();
|
|
|
|
|
|
public Size InterpResolution
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_interpResolution.IsEmpty)
|
|
|
|
|
|
_interpResolution = InterpolateUtils.GetInterpolationResolution(FfmpegCommands.ModuloMode.ForInterpolation, InputResolution);
|
|
|
|
|
|
return _interpResolution;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-08-23 16:50:18 +02:00
|
|
|
|
|
|
|
|
|
|
public bool alpha;
|
|
|
|
|
|
public bool stepByStep;
|
|
|
|
|
|
|
|
|
|
|
|
public string framesExt;
|
|
|
|
|
|
public string interpExt;
|
|
|
|
|
|
|
2021-09-29 11:22:43 +02:00
|
|
|
|
public InterpSettings() { }
|
|
|
|
|
|
|
2023-12-22 05:20:22 +01:00
|
|
|
|
public void InitArgs ()
|
|
|
|
|
|
{
|
2025-02-06 20:38:18 +01:00
|
|
|
|
outFps = inFps == null ? new Fraction() : inFps * (double)interpFactor;
|
2024-11-28 16:08:04 +01:00
|
|
|
|
outFpsResampled = new Fraction(Config.Get(Config.Key.maxFps));
|
2021-08-23 16:50:18 +02:00
|
|
|
|
alpha = false;
|
|
|
|
|
|
stepByStep = false;
|
|
|
|
|
|
framesExt = "";
|
|
|
|
|
|
interpExt = "";
|
2021-11-24 21:08:29 +01:00
|
|
|
|
_inputResolution = new Size(0, 0);
|
2025-02-10 21:03:05 +01:00
|
|
|
|
noRedupe = dedupe && interpFactor == 1;
|
2024-11-28 16:08:04 +01:00
|
|
|
|
SetPaths(inPath);
|
2024-06-24 18:32:35 +02:00
|
|
|
|
RefreshExtensions(ai: ai);
|
2021-08-23 16:50:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-28 16:08:04 +01:00
|
|
|
|
private void SetPaths (string inputPath)
|
2021-08-23 16:50:18 +02:00
|
|
|
|
{
|
2024-12-03 00:40:24 +01:00
|
|
|
|
if (!File.Exists(inputPath) && !Directory.Exists(inputPath))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2024-11-28 16:08:04 +01:00
|
|
|
|
inPath = inputPath;
|
|
|
|
|
|
outPath = (Config.GetInt("outFolderLoc") == 0) ? inputPath.GetParentDir() : Config.Get("custOutDir").Trim();
|
2021-08-23 16:50:18 +02:00
|
|
|
|
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
|
|
|
|
|
|
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
|
|
|
|
|
|
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
|
|
|
|
|
|
inputIsFrames = IoUtils.IsPathDirectory(inPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RefreshAlpha ()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2022-07-27 15:18:37 +02:00
|
|
|
|
bool alphaModel = model.SupportsAlpha;
|
2023-01-15 17:23:49 +01:00
|
|
|
|
bool pngOutput = outSettings.Encoder == Enums.Encoding.Encoder.Png;
|
|
|
|
|
|
bool gifOutput = outSettings.Encoder == Enums.Encoding.Encoder.Gif;
|
2023-02-20 19:30:23 +01:00
|
|
|
|
bool proResAlpha = outSettings.Encoder == Enums.Encoding.Encoder.ProResKs && OutputUtils.AlphaFormats.Contains(outSettings.PixelFormat);
|
2023-01-15 17:23:49 +01:00
|
|
|
|
bool outputSupportsAlpha = pngOutput || gifOutput || proResAlpha;
|
2024-09-03 22:08:38 +02:00
|
|
|
|
string ext = inputIsFrames ? Path.GetExtension(IoUtils.GetFilesSorted(inPath).First()).Lower() : Path.GetExtension(inPath).Lower();
|
2021-08-30 10:36:07 +02:00
|
|
|
|
alpha = (alphaModel && outputSupportsAlpha && (ext == ".gif" || ext == ".png" || ext == ".apng" || ext == ".mov"));
|
2023-01-15 17:23:49 +01:00
|
|
|
|
Logger.Log($"RefreshAlpha: model.supportsAlpha = {alphaModel} - outputSupportsAlpha = {outputSupportsAlpha} - input ext: {ext} => alpha = {alpha}", true);
|
2021-08-23 16:50:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Logger.Log("RefreshAlpha Error: " + e.Message, true);
|
|
|
|
|
|
alpha = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public enum FrameType { Import, Interp, Both };
|
|
|
|
|
|
|
2024-08-21 14:45:46 +02:00
|
|
|
|
public void RefreshExtensions(FrameType type = FrameType.Both, AiInfo ai = null)
|
2021-08-23 16:50:18 +02:00
|
|
|
|
{
|
2024-06-24 18:32:35 +02:00
|
|
|
|
if(ai == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Interpolate.currentSettings == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
ai = Interpolate.currentSettings.ai;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-15 17:23:49 +01:00
|
|
|
|
bool pngOutput = outSettings.Encoder == Enums.Encoding.Encoder.Png;
|
2023-02-20 19:30:23 +01:00
|
|
|
|
bool aviHqChroma = outSettings.Format == Enums.Output.Format.Avi && OutputUtils.AlphaFormats.Contains(outSettings.PixelFormat);
|
|
|
|
|
|
bool proresHqChroma = outSettings.Encoder == Enums.Encoding.Encoder.ProResKs && OutputUtils.AlphaFormats.Contains(outSettings.PixelFormat);
|
2021-08-23 16:50:18 +02:00
|
|
|
|
bool forceHqChroma = pngOutput || aviHqChroma || proresHqChroma;
|
2024-06-24 18:32:35 +02:00
|
|
|
|
bool tiffSupport = !ai.NameInternal.Upper().EndsWith("NCNN"); // NCNN binaries can't load TIFF (unlike OpenCV, ffmpeg etc)
|
|
|
|
|
|
string losslessExt = tiffSupport ? ".tiff" : ".png";
|
|
|
|
|
|
bool allowJpegImport = Config.GetBool(Config.Key.jpegFrames) && !(alpha || forceHqChroma); // Force PNG if alpha is enabled, or output is not 4:2:0 subsampled
|
|
|
|
|
|
bool allowJpegExport = Config.GetBool(Config.Key.jpegInterp) && !(alpha || forceHqChroma);
|
2021-08-23 16:50:18 +02:00
|
|
|
|
|
|
|
|
|
|
Logger.Log($"RefreshExtensions({type}) - alpha = {alpha} pngOutput = {pngOutput} aviHqChroma = {aviHqChroma} proresHqChroma = {proresHqChroma}", true);
|
|
|
|
|
|
|
2024-06-24 18:32:35 +02:00
|
|
|
|
if (type == FrameType.Both || type == FrameType.Import)
|
|
|
|
|
|
framesExt = allowJpegImport ? ".jpg" : losslessExt;
|
2021-08-23 16:50:18 +02:00
|
|
|
|
|
2024-06-24 18:32:35 +02:00
|
|
|
|
if (type == FrameType.Both || type == FrameType.Interp)
|
|
|
|
|
|
interpExt = allowJpegExport ? ".jpg" : ".png";
|
2021-08-23 16:50:18 +02:00
|
|
|
|
|
|
|
|
|
|
Logger.Log($"RefreshExtensions - Using '{framesExt}' for imported frames, using '{interpExt}' for interpolated frames", true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string Serialize ()
|
|
|
|
|
|
{
|
|
|
|
|
|
string s = $"INPATH|{inPath}\n";
|
|
|
|
|
|
s += $"OUTPATH|{outPath}\n";
|
2022-07-21 10:08:53 +02:00
|
|
|
|
s += $"AI|{ai.NameInternal}\n";
|
2021-08-23 16:50:18 +02:00
|
|
|
|
s += $"INFPSDETECTED|{inFpsDetected}\n";
|
|
|
|
|
|
s += $"INFPS|{inFps}\n";
|
|
|
|
|
|
s += $"OUTFPS|{outFps}\n";
|
|
|
|
|
|
s += $"INTERPFACTOR|{interpFactor}\n";
|
2023-01-15 17:23:49 +01:00
|
|
|
|
s += $"OUTMODE|{outSettings.Format}\n";
|
2022-07-27 15:18:37 +02:00
|
|
|
|
s += $"MODEL|{model.Name}\n";
|
2021-11-24 21:08:29 +01:00
|
|
|
|
s += $"INPUTRES|{InputResolution.Width}x{InputResolution.Height}\n";
|
2024-11-12 22:13:59 +01:00
|
|
|
|
s += $"OUTPUTRES|{OutputResolution.Width}x{OutputResolution.Height}\n";
|
2021-08-23 16:50:18 +02:00
|
|
|
|
s += $"ALPHA|{alpha}\n";
|
|
|
|
|
|
s += $"STEPBYSTEP|{stepByStep}\n";
|
|
|
|
|
|
s += $"FRAMESEXT|{framesExt}\n";
|
|
|
|
|
|
s += $"INTERPEXT|{interpExt}\n";
|
|
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|