2020-11-23 16:51:05 +01:00
using Flowframes.IO ;
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
using System.Runtime.InteropServices ;
using System.Text ;
using System.Threading.Tasks ;
using Flowframes.OS ;
using Flowframes.UI ;
using Flowframes.Main ;
namespace Flowframes
{
class AiProcess
{
2020-11-24 12:28:47 +01:00
public static bool hasShownError ;
2020-11-23 16:51:05 +01:00
public static Process currentAiProcess ;
public static Stopwatch processTime = new Stopwatch ( ) ;
2020-11-25 14:04:31 +01:00
public static int lastStartupTimeMs = 1000 ;
2020-11-25 20:31:21 +01:00
static void Init ( Process proc , int startupTimeMs , string defaultExt = "png" )
2020-11-23 16:51:05 +01:00
{
2020-11-25 14:04:31 +01:00
lastStartupTimeMs = startupTimeMs ;
2020-11-25 12:40:17 +01:00
InterpolateUtils . lastExt = defaultExt ;
2020-11-23 16:51:05 +01:00
if ( Config . GetBool ( "jpegInterps" ) ) InterpolateUtils . lastExt = "jpg" ;
2020-11-24 12:28:47 +01:00
processTime . Restart ( ) ;
currentAiProcess = proc ;
hasShownError = false ;
}
2020-11-23 16:51:05 +01:00
2020-11-24 12:28:47 +01:00
public static async Task RunDainNcnn ( string framesPath , string outPath , int targetFrames , int tilesize )
{
2020-11-23 16:51:05 +01:00
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -t {tilesize} -g {Config.Get(" ncnnGpus ")}" ;
string dainDir = Path . Combine ( Paths . GetPkgPath ( ) , Path . GetFileNameWithoutExtension ( Packages . dainNcnn . fileName ) ) ;
Process dain = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2020-11-25 14:04:31 +01:00
Init ( dain , 1500 ) ;
2020-11-23 16:51:05 +01:00
dain . StartInfo . Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args} -f {InterpolateUtils.lastExt}" ;
Logger . Log ( "Running DAIN..." , false ) ;
Logger . Log ( "cmd.exe " + dain . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2020-11-25 17:27:15 +01:00
dain . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "dain-ncnn-log.txt" ) ; } ;
2020-11-23 16:51:05 +01:00
dain . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "dain-ncnn-log.txt" ) ; } ;
}
dain . Start ( ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
dain . BeginOutputReadLine ( ) ;
dain . BeginErrorReadLine ( ) ;
}
while ( ! dain . HasExited )
await Task . Delay ( 1 ) ;
2020-11-25 17:27:15 +01:00
if ( Interpolate . canceled ) return ;
Magick . MagickDedupe . ZeroPadDir ( outPath , InterpolateUtils . lastExt , 8 ) ;
2020-11-23 16:51:05 +01:00
Logger . Log ( $"Done running DAIN - Interpolation took " + FormatUtils . Time ( processTime . Elapsed ) ) ;
processTime . Stop ( ) ;
}
public static async Task RunCainNcnnMulti ( string framesPath , string outPath , int tilesize , int times )
{
Logger . Log ( "Running CAIN..." , false ) ;
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get(" ncnnGpus ")}" ;
await RunCainPartial ( args ) ;
if ( times = = 4 | | times = = 8 ) // #2
{
2020-11-25 17:27:15 +01:00
if ( Interpolate . canceled ) return ;
2020-11-23 16:51:05 +01:00
Logger . Log ( "Re-Running CAIN for 4x interpolation..." , false ) ;
string run1ResultsPath = outPath + "-run1" ;
IOUtils . TryDeleteIfExists ( run1ResultsPath ) ;
Directory . Move ( outPath , run1ResultsPath ) ;
Directory . CreateDirectory ( outPath ) ;
args = $" -v -i {run1ResultsPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get(" ncnnGpus ")}" ;
await RunCainPartial ( args ) ;
Directory . Delete ( run1ResultsPath , true ) ;
}
if ( times = = 8 ) // #3
{
2020-11-25 17:27:15 +01:00
if ( Interpolate . canceled ) return ;
2020-11-23 16:51:05 +01:00
Logger . Log ( "Re-Running CAIN for 8x interpolation..." , false ) ;
string run2ResultsPath = outPath + "-run2" ;
IOUtils . TryDeleteIfExists ( run2ResultsPath ) ;
Directory . Move ( outPath , run2ResultsPath ) ;
Directory . CreateDirectory ( outPath ) ;
args = $" -v -i {run2ResultsPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get(" ncnnGpus ")}" ;
await RunCainPartial ( args ) ;
Directory . Delete ( run2ResultsPath , true ) ;
}
2020-11-25 17:27:15 +01:00
if ( Interpolate . canceled ) return ;
Magick . MagickDedupe . ZeroPadDir ( outPath , InterpolateUtils . lastExt , 8 ) ;
2020-11-23 16:51:05 +01:00
Logger . Log ( $"Done running CAIN - Interpolation took " + FormatUtils . Time ( processTime . Elapsed ) ) ;
processTime . Stop ( ) ;
}
static async Task RunCainPartial ( string args )
{
string cainDir = Path . Combine ( Paths . GetPkgPath ( ) , Path . GetFileNameWithoutExtension ( Packages . cainNcnn . fileName ) ) ;
string cainExe = "cain-ncnn-vulkan.exe" ;
Process cain = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2020-11-25 14:04:31 +01:00
Init ( cain , 1500 ) ;
2020-11-23 16:51:05 +01:00
cain . StartInfo . Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {cainDir.Wrap()} & {cainExe} {args} -f {InterpolateUtils.lastExt}" ;
Logger . Log ( "cmd.exe " + cain . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2020-11-25 17:27:15 +01:00
cain . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "cain-ncnn-log.txt" ) ; } ;
2020-11-23 16:51:05 +01:00
cain . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "cain-ncnn-log.txt" ) ; } ;
}
cain . Start ( ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
cain . BeginOutputReadLine ( ) ;
cain . BeginErrorReadLine ( ) ;
}
while ( ! cain . HasExited ) await Task . Delay ( 1 ) ;
}
public static async Task RunRifeCuda ( string framesPath , int interpFactor )
{
string script = "interp-parallel.py" ;
2020-11-25 12:40:17 +01:00
if ( Config . GetInt ( "rifeMode" ) = = 0 | | IOUtils . GetAmountOfFiles ( framesPath , false ) < 10 )
2020-11-23 16:51:05 +01:00
script = "interp-basic.py" ;
string rifeDir = Path . Combine ( Paths . GetPkgPath ( ) , Path . GetFileNameWithoutExtension ( Packages . rifeCuda . fileName ) ) ;
Process rifePy = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2020-11-25 20:31:21 +01:00
Init ( rifePy , 3000 , "png" ) ;
2020-11-23 16:51:05 +01:00
string args = $" --input {framesPath.Wrap()} --times {(int)Math.Log(interpFactor, 2)}" ;
rifePy . StartInfo . Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {rifeDir.Wrap()} & " +
$"set CUDA_VISIBLE_DEVICES={Config.Get(" torchGpus ")} & {Python.GetPyCmd()} {script} {args} --imgformat {InterpolateUtils.lastExt}" ;
Logger . Log ( $"Running RIFE ({script})..." , false ) ;
Logger . Log ( "cmd.exe " + rifePy . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2020-11-25 17:27:15 +01:00
rifePy . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "rife-cuda-log.txt" ) ; } ;
2020-11-23 16:51:05 +01:00
rifePy . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "rife-cuda-log.txt" ) ; } ;
}
rifePy . Start ( ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
rifePy . BeginOutputReadLine ( ) ;
rifePy . BeginErrorReadLine ( ) ;
}
while ( ! rifePy . HasExited )
await Task . Delay ( 1 ) ;
Logger . Log ( $"Done running RIFE - Interpolation took " + FormatUtils . Time ( processTime . Elapsed ) ) ;
processTime . Stop ( ) ;
2020-11-25 14:04:31 +01:00
}
public static async Task RunRifeNcnn ( string framesPath , string outPath , int interpFactor , int tilesize )
{
2020-11-25 17:27:15 +01:00
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -t {tilesize} -g {Config.Get(" ncnnGpus ")} -f {InterpolateUtils.lastExt} -j 4:{Config.Get(" ncnnThreads ")}:4" ;
2020-11-25 14:04:31 +01:00
string dir = Path . Combine ( Paths . GetPkgPath ( ) , Path . GetFileNameWithoutExtension ( Packages . rifeNcnn . fileName ) ) ;
Process rifeNcnn = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
Init ( rifeNcnn , 750 ) ;
2020-11-25 17:27:15 +01:00
rifeNcnn . StartInfo . Arguments = $"{OSUtils.GetHiddenCmdArg()} cd /D {dir.Wrap()} & rife-ncnn-vulkan.exe {args}" ;
2020-11-25 14:04:31 +01:00
Logger . Log ( "Running RIFE..." , false ) ;
Logger . Log ( "cmd.exe " + rifeNcnn . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2020-11-25 17:27:15 +01:00
rifeNcnn . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "rife-ncnn-log.txt" ) ; } ;
2020-11-25 14:04:31 +01:00
rifeNcnn . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "rife-ncnn-log.txt" ) ; } ;
}
rifeNcnn . Start ( ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
rifeNcnn . BeginOutputReadLine ( ) ;
rifeNcnn . BeginErrorReadLine ( ) ;
}
while ( ! rifeNcnn . HasExited )
await Task . Delay ( 1 ) ;
2020-11-25 17:27:15 +01:00
if ( Interpolate . canceled ) return ;
2020-11-25 14:04:31 +01:00
Magick . MagickDedupe . ZeroPadDir ( outPath , InterpolateUtils . lastExt , 8 ) ;
Logger . Log ( $"Done running RIFE - Interpolation took " + FormatUtils . Time ( processTime . Elapsed ) ) ;
processTime . Stop ( ) ;
}
2020-11-23 16:51:05 +01:00
static void LogOutput ( string line , string logFilename )
{
2020-11-25 17:27:15 +01:00
if ( string . IsNullOrWhiteSpace ( line ) )
2020-11-23 16:51:05 +01:00
return ;
Logger . LogToFile ( line , false , logFilename ) ;
2020-11-25 17:27:15 +01:00
if ( line . Contains ( "ff:nocuda-cpu" ) )
Logger . Log ( "WARNING: CUDA-capable GPU device is not available, running on CPU instead!" ) ;
2020-11-24 12:28:47 +01:00
if ( ! hasShownError & & line . ToLower ( ) . Contains ( "out of memory" ) )
{
hasShownError = true ;
InterpolateUtils . ShowMessage ( $"Your GPU ran out of VRAM! Please try a video with a lower resolution or use the Max Video Size option in the settings.\n\n{line}" , "Error" ) ;
}
if ( ! hasShownError & & line . ToLower ( ) . Contains ( "modulenotfounderror" ) )
{
hasShownError = true ;
2020-11-23 16:51:05 +01:00
InterpolateUtils . ShowMessage ( $"A python module is missing. Check {logFilename} for details.\n\n{line}" , "Error" ) ;
2020-11-24 12:28:47 +01:00
}
2020-11-23 16:51:05 +01:00
2020-11-24 12:28:47 +01:00
if ( ! hasShownError & & line . ToLower ( ) . Contains ( "no longer supports this gpu" ) )
{
hasShownError = true ;
2020-11-23 16:51:05 +01:00
InterpolateUtils . ShowMessage ( "Your GPU seems to be outdated and is not supported!\n\n{line}" , "Error" ) ;
2020-11-24 12:28:47 +01:00
}
if ( ! hasShownError & & line . Contains ( "RuntimeError" ) )
{
hasShownError = true ;
InterpolateUtils . ShowMessage ( $"An error occured during interpolation!\n\n{line}" , "Error" ) ;
}
2020-11-23 16:51:05 +01:00
}
}
}