2021-08-23 16:50:18 +02:00
using Flowframes.Media ;
using Flowframes.Data ;
using Flowframes.IO ;
using Flowframes.Main ;
using Flowframes.MiscUtils ;
using Flowframes.Ui ;
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Threading.Tasks ;
using Microsoft.VisualBasic.Logging ;
namespace Flowframes
{
public class InterpSettings
{
public string inPath ;
public string outPath ;
2022-05-31 22:17:22 +02:00
public string FullOutPath { get ; set ; } = "" ;
2021-08-23 16:50:18 +02:00
public AI ai ;
public Fraction inFps ;
public Fraction inFpsDetected ;
public Fraction outFps ;
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 ;
2021-11-24 21:08:29 +01:00
private Size _inputResolution ;
public Size InputResolution { get { RefreshInputRes ( ) ; return _inputResolution ; } }
2023-01-08 14:17:11 +01:00
public Size ScaledResolution { get { return InterpolateUtils . GetOutputResolution ( InputResolution , false ) ; } }
public Size ScaledPaddedResolution { get { return InterpolateUtils . GetOutputResolution ( InputResolution , true ) ; } }
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-01-18 14:55:38 +01:00
public InterpSettings ( string inPathArg , string outPathArg , AI aiArg , Fraction inFpsDetectedArg , Fraction inFpsArg , float interpFactorArg , float itsScale , OutputSettings outSettingsArg , ModelCollection . ModelInfo modelArg )
2021-08-23 16:50:18 +02:00
{
inPath = inPathArg ;
outPath = outPathArg ;
ai = aiArg ;
inFpsDetected = inFpsDetectedArg ;
inFps = inFpsArg ;
interpFactor = interpFactorArg ;
2022-04-22 10:34:59 +02:00
outFps = inFpsArg * ( double ) interpFactorArg ;
2021-08-28 10:21:52 +02:00
outItsScale = itsScale ;
2023-01-15 17:23:49 +01:00
outSettings = outSettingsArg ;
2021-08-23 16:50:18 +02:00
model = modelArg ;
alpha = false ;
stepByStep = false ;
framesExt = "" ;
interpExt = "" ;
try
{
tempFolder = InterpolateUtils . GetTempFolderLoc ( inPath , outPath ) ;
framesFolder = Path . Combine ( tempFolder , Paths . framesDir ) ;
interpFolder = Path . Combine ( tempFolder , Paths . interpDir ) ;
inputIsFrames = IoUtils . IsPathDirectory ( inPath ) ;
}
catch
{
Logger . Log ( "Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder." , true ) ;
tempFolder = "" ;
framesFolder = "" ;
interpFolder = "" ;
inputIsFrames = false ;
}
2021-11-24 21:08:29 +01:00
_inputResolution = new Size ( 0 , 0 ) ;
2021-08-23 16:50:18 +02:00
RefreshExtensions ( ) ;
}
public InterpSettings ( string serializedData )
{
inPath = "" ;
outPath = "" ;
2022-06-09 00:30:58 +02:00
ai = null ;
2021-08-23 16:50:18 +02:00
inFpsDetected = new Fraction ( ) ;
inFps = new Fraction ( ) ;
interpFactor = 0 ;
outFps = new Fraction ( ) ;
2023-01-18 14:55:38 +01:00
outSettings = new OutputSettings ( ) ;
2021-08-23 16:50:18 +02:00
model = null ;
alpha = false ;
stepByStep = false ;
2021-11-24 21:08:29 +01:00
_inputResolution = new Size ( 0 , 0 ) ;
2021-08-23 16:50:18 +02:00
framesExt = "" ;
interpExt = "" ;
Dictionary < string , string > entries = new Dictionary < string , string > ( ) ;
foreach ( string line in serializedData . SplitIntoLines ( ) )
{
if ( line . Length < 3 ) continue ;
string [ ] keyValuePair = line . Split ( '|' ) ;
entries . Add ( keyValuePair [ 0 ] , keyValuePair [ 1 ] ) ;
}
2023-01-15 17:23:49 +01:00
// TODO: Rework this ugly stuff, JSON?
2021-08-23 16:50:18 +02:00
foreach ( KeyValuePair < string , string > entry in entries )
{
switch ( entry . Key )
{
case "INPATH" : inPath = entry . Value ; break ;
case "OUTPATH" : outPath = entry . Value ; break ;
case "AI" : ai = Implementations . GetAi ( entry . Value ) ; break ;
case "INFPSDETECTED" : inFpsDetected = new Fraction ( entry . Value ) ; break ;
case "INFPS" : inFps = new Fraction ( entry . Value ) ; break ;
case "OUTFPS" : outFps = new Fraction ( entry . Value ) ; break ;
case "INTERPFACTOR" : interpFactor = float . Parse ( entry . Value ) ; break ;
2023-01-15 17:23:49 +01:00
case "OUTMODE" : outSettings . Format = ( Enums . Output . Format ) Enum . Parse ( typeof ( Enums . Output . Format ) , entry . Value ) ; break ;
2021-08-23 16:50:18 +02:00
case "MODEL" : model = AiModels . GetModelByName ( ai , entry . Value ) ; break ;
2021-11-24 21:08:29 +01:00
case "INPUTRES" : _inputResolution = FormatUtils . ParseSize ( entry . Value ) ; break ;
2021-08-23 16:50:18 +02:00
case "ALPHA" : alpha = bool . Parse ( entry . Value ) ; break ;
case "STEPBYSTEP" : stepByStep = bool . Parse ( entry . Value ) ; break ;
case "FRAMESEXT" : framesExt = entry . Value ; break ;
case "INTERPEXT" : interpExt = entry . Value ; break ;
}
}
try
{
tempFolder = InterpolateUtils . GetTempFolderLoc ( inPath , outPath ) ;
framesFolder = Path . Combine ( tempFolder , Paths . framesDir ) ;
interpFolder = Path . Combine ( tempFolder , Paths . interpDir ) ;
inputIsFrames = IoUtils . IsPathDirectory ( inPath ) ;
}
catch
{
Logger . Log ( "Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder." , true ) ;
tempFolder = "" ;
framesFolder = "" ;
interpFolder = "" ;
inputIsFrames = false ;
}
RefreshExtensions ( ) ;
}
public void UpdatePaths ( string inPathArg , string outPathArg )
{
inPath = inPathArg ;
outPath = outPathArg ;
tempFolder = InterpolateUtils . GetTempFolderLoc ( inPath , outPath ) ;
framesFolder = Path . Combine ( tempFolder , Paths . framesDir ) ;
interpFolder = Path . Combine ( tempFolder , Paths . interpDir ) ;
inputIsFrames = IoUtils . IsPathDirectory ( inPath ) ;
}
2021-11-24 21:08:29 +01:00
async Task RefreshInputRes ( )
2021-08-23 16:50:18 +02:00
{
2021-11-24 21:08:29 +01:00
if ( _inputResolution . IsEmpty )
_inputResolution = await GetMediaResolutionCached . GetSizeAsync ( inPath ) ;
2021-08-23 16:50:18 +02:00
}
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 ;
bool proResAlpha = outSettings . Encoder = = Enums . Encoding . Encoder . ProResKs & & Config . GetInt ( Config . Key . proResProfile ) > 3 ; // TODO: CHECK IF WORKS WITH NEW ENCODING SETTINGS CODE
bool outputSupportsAlpha = pngOutput | | gifOutput | | proResAlpha ;
2022-10-14 09:00:47 +02:00
string ext = inputIsFrames ? Path . GetExtension ( IoUtils . GetFilesSorted ( inPath ) . First ( ) ) . ToLowerInvariant ( ) : Path . GetExtension ( inPath ) . ToLowerInvariant ( ) ;
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 } ;
public void RefreshExtensions ( FrameType type = FrameType . Both )
{
2023-01-15 17:23:49 +01:00
bool pngOutput = outSettings . Encoder = = Enums . Encoding . Encoder . Png ;
bool aviHqChroma = outSettings . Format = = Enums . Output . Format . Avi & & outSettings . PixelFormat ! = Enums . Encoding . PixelFormat . Yuv420P ; // TODO: CHECK IF WORKS WITH NEW ENCODING SETTINGS CODE
bool proresHqChroma = outSettings . Encoder = = Enums . Encoding . Encoder . ProResKs & & Config . GetInt ( Config . Key . proResProfile ) > 3 ; // TODO: CHECK IF WORKS WITH NEW ENCODING SETTINGS CODE
2021-08-23 16:50:18 +02:00
bool forceHqChroma = pngOutput | | aviHqChroma | | proresHqChroma ;
Logger . Log ( $"RefreshExtensions({type}) - alpha = {alpha} pngOutput = {pngOutput} aviHqChroma = {aviHqChroma} proresHqChroma = {proresHqChroma}" , true ) ;
if ( alpha | | forceHqChroma ) // Force PNG if alpha is enabled, or output is not 4:2:0 subsampled
{
if ( type = = FrameType . Both | | type = = FrameType . Import )
framesExt = ".png" ;
if ( type = = FrameType . Both | | type = = FrameType . Interp )
interpExt = ".png" ;
}
else
{
if ( type = = FrameType . Both | | type = = FrameType . Import )
framesExt = ( Config . GetBool ( Config . Key . jpegFrames ) ? ".jpg" : ".png" ) ;
if ( type = = FrameType . Both | | type = = FrameType . Interp )
interpExt = ( Config . GetBool ( Config . Key . jpegInterp ) ? ".jpg" : ".png" ) ;
}
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" ;
s + = $"OUTPUTRES|{ScaledResolution.Width}x{ScaledResolution.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 ;
}
}
}