2020-11-23 16:51:05 +01:00
using Flowframes.IO ;
using System ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
using System.Threading.Tasks ;
using Flowframes.OS ;
using Flowframes.UI ;
using Flowframes.Main ;
2020-12-04 16:53:39 +01:00
using Flowframes.Data ;
2020-12-27 22:52:14 +01:00
using Flowframes.MiscUtils ;
2021-02-05 15:52:44 +01:00
using Flowframes.Media ;
2020-11-23 16:51:05 +01:00
namespace Flowframes
{
class AiProcess
{
2020-11-24 12:28:47 +01:00
public static bool hasShownError ;
2021-03-10 20:45:48 +01:00
public static Process lastAiProcess ;
2020-11-23 16:51:05 +01:00
public static Stopwatch processTime = new Stopwatch ( ) ;
2020-11-26 00:07:45 +01:00
public static Stopwatch processTimeMulti = new Stopwatch ( ) ;
2020-11-23 16:51:05 +01:00
2020-11-25 14:04:31 +01:00
public static int lastStartupTimeMs = 1000 ;
2020-12-20 21:25:34 +01:00
static string lastInPath ;
2020-11-25 14:04:31 +01:00
2021-03-10 20:45:48 +01:00
public static void Kill ( )
{
if ( lastAiProcess = = null ) return ;
try
{
2021-04-29 22:57:00 +02:00
AiProcessSuspend . SetRunning ( false ) ;
2021-03-10 20:45:48 +01:00
OSUtils . KillProcessTree ( lastAiProcess . Id ) ;
}
catch ( Exception e )
{
Logger . Log ( $"Failed to kill currentAiProcess process tree: {e.Message}" , true ) ;
}
}
2021-01-18 15:32:45 +01:00
static void AiStarted ( Process proc , int startupTimeMs , string inPath = "" )
2020-11-23 16:51:05 +01:00
{
2020-11-25 14:04:31 +01:00
lastStartupTimeMs = startupTimeMs ;
2020-11-24 12:28:47 +01:00
processTime . Restart ( ) ;
2021-03-10 20:45:48 +01:00
lastAiProcess = proc ;
2021-04-29 22:57:00 +02:00
AiProcessSuspend . SetRunning ( true ) ;
2020-12-20 21:25:34 +01:00
lastInPath = string . IsNullOrWhiteSpace ( inPath ) ? Interpolate . current . framesFolder : inPath ;
2020-11-24 12:28:47 +01:00
hasShownError = false ;
}
2020-11-23 16:51:05 +01:00
2021-02-01 18:05:50 +01:00
static void SetProgressCheck ( string interpPath , float factor )
2021-01-18 15:32:45 +01:00
{
2021-04-29 22:57:00 +02:00
int frames = IOUtils . GetAmountOfFiles ( lastInPath , false ) ;
2021-02-01 18:05:50 +01:00
int target = ( ( frames * factor ) - ( factor - 1 ) ) . RoundToInt ( ) ;
2021-04-22 16:15:17 +02:00
InterpolationProgress . progressPaused = false ;
InterpolationProgress . currentFactor = factor ;
2021-01-18 15:32:45 +01:00
2021-04-22 16:15:17 +02:00
if ( InterpolationProgress . progCheckRunning )
InterpolationProgress . targetFrames = target ;
2021-01-18 15:32:45 +01:00
else
2021-04-22 16:15:17 +02:00
InterpolationProgress . GetProgressByFrameAmount ( interpPath , target ) ;
2021-01-18 15:32:45 +01:00
}
2021-02-11 21:05:45 +01:00
static async Task AiFinished ( string aiName )
2020-11-30 20:32:33 +01:00
{
2021-01-27 12:04:22 +01:00
if ( Interpolate . canceled ) return ;
2020-11-30 20:32:33 +01:00
Program . mainForm . SetProgress ( 100 ) ;
2021-04-29 22:57:00 +02:00
AiProcessSuspend . SetRunning ( false ) ;
2021-04-30 10:36:44 +02:00
int interpolatedFrames = IOUtils . GetAmountOfFiles ( Interpolate . current . interpFolder , false , "*" + Interpolate . current . interpExt ) ;
InterpolationProgress . UpdateInterpProgress ( interpolatedFrames , InterpolationProgress . targetFrames ) ;
2021-04-22 16:15:17 +02:00
string logStr = $"Done running {aiName} - Interpolation took {FormatUtils.Time(processTime.Elapsed)}. Peak Output FPS: {InterpolationProgress.peakFpsOut.ToString(" 0.00 ")}" ;
2021-04-02 14:36:08 +02:00
2020-12-01 16:54:12 +01:00
if ( Interpolate . currentlyUsingAutoEnc & & AutoEncode . HasWorkToDo ( ) )
2021-04-02 14:36:08 +02:00
{
2020-11-30 20:32:33 +01:00
logStr + = " - Waiting for encoding to finish..." ;
2021-04-02 14:36:08 +02:00
Program . mainForm . SetStatus ( "Creating output video from frames..." ) ;
}
2020-11-30 20:32:33 +01:00
Logger . Log ( logStr ) ;
processTime . Stop ( ) ;
2021-01-11 11:45:38 +01:00
2021-04-30 10:36:44 +02:00
if ( interpolatedFrames < 3 )
{
string amount = interpolatedFrames > 0 ? $"Only {interpolatedFrames}" : "No" ;
Interpolate . Cancel ( $"Interpolation failed - {amount} interpolated frames were created." ) ;
return ;
}
2021-01-06 23:33:00 +01:00
while ( Interpolate . currentlyUsingAutoEnc & & Program . busy )
2021-01-06 21:44:09 +01:00
{
2021-03-10 20:45:48 +01:00
if ( AvProcess . lastAvProcess ! = null & & ! AvProcess . lastAvProcess . HasExited & & AvProcess . lastTask = = AvProcess . TaskType . Encode )
2021-01-06 22:51:04 +01:00
{
string lastLine = AvProcess . lastOutputFfmpeg . SplitIntoLines ( ) . Last ( ) ;
2021-01-06 23:33:00 +01:00
Logger . Log ( lastLine . Trim ( ) . TrimWhitespaces ( ) , false , Logger . GetLastLine ( ) . Contains ( "frame" ) ) ;
2021-01-06 22:51:04 +01:00
}
2021-02-01 21:50:05 +01:00
if ( AvProcess . timeSinceLastOutput . IsRunning & & AvProcess . timeSinceLastOutput . ElapsedMilliseconds > 2500 )
2021-01-11 11:45:38 +01:00
break ;
2021-01-26 16:45:02 +01:00
2021-01-11 11:45:38 +01:00
await Task . Delay ( 500 ) ;
2021-01-06 21:44:09 +01:00
}
2021-01-27 11:41:05 +01:00
if ( ! Interpolate . canceled & & Interpolate . current . alpha )
{
Logger . Log ( "Processing alpha..." ) ;
string rgbInterpDir = Path . Combine ( Interpolate . current . tempFolder , Paths . interpDir ) ;
string alphaInterpDir = Path . Combine ( Interpolate . current . tempFolder , Paths . interpDir + Paths . alphaSuffix ) ;
if ( ! Directory . Exists ( alphaInterpDir ) ) return ;
2021-02-05 15:52:44 +01:00
await FfmpegAlpha . MergeAlphaIntoRgb ( rgbInterpDir , Padding . interpFrames , alphaInterpDir , Padding . interpFrames , false ) ;
2021-01-27 11:41:05 +01:00
}
2020-11-30 20:32:33 +01:00
}
2021-02-01 18:05:50 +01:00
public static async Task RunRifeCuda ( string framesPath , float interpFactor , string mdl )
2020-11-23 16:51:05 +01:00
{
2021-02-09 18:23:22 +01:00
if ( Interpolate . currentlyUsingAutoEnc ) // Ensure AutoEnc is not paused
AutoEncode . paused = false ;
2021-03-01 18:13:19 +01:00
try
2020-12-12 20:25:03 +01:00
{
2021-03-11 12:58:18 +01:00
string rifeDir = Path . Combine ( Paths . GetPkgPath ( ) , Networks . rifeCuda . pkgDir ) ;
2021-03-01 18:13:19 +01:00
string script = "rife.py" ;
2020-12-12 20:25:03 +01:00
2021-03-01 18:13:19 +01:00
if ( ! File . Exists ( Path . Combine ( rifeDir , script ) ) )
{
Interpolate . Cancel ( "RIFE script not found! Make sure you didn't modify any files." ) ;
return ;
}
2021-01-18 15:32:45 +01:00
2021-03-01 18:13:19 +01:00
await RunRifeCudaProcess ( framesPath , Paths . interpDir , script , interpFactor , mdl ) ;
if ( ! Interpolate . canceled & & Interpolate . current . alpha )
{
2021-04-22 16:15:17 +02:00
InterpolationProgress . progressPaused = true ;
2021-03-01 18:13:19 +01:00
Logger . Log ( "Interpolating alpha channel..." ) ;
await RunRifeCudaProcess ( framesPath + Paths . alphaSuffix , Paths . interpDir + Paths . alphaSuffix , script , interpFactor , mdl ) ;
}
}
catch ( Exception e )
2021-01-18 15:32:45 +01:00
{
2021-03-01 18:13:19 +01:00
Logger . Log ( "Error running RIFE-CUDA: " + e . Message ) ;
2021-01-18 15:32:45 +01:00
}
2021-02-11 21:05:45 +01:00
await AiFinished ( "RIFE" ) ;
2021-01-18 15:32:45 +01:00
}
2021-02-01 18:05:50 +01:00
public static async Task RunRifeCudaProcess ( string inPath , string outDir , string script , float interpFactor , string mdl )
2021-01-18 15:32:45 +01:00
{
2021-01-26 16:45:02 +01:00
string outPath = Path . Combine ( inPath . GetParentDir ( ) , outDir ) ;
2021-03-14 15:26:52 +01:00
Directory . CreateDirectory ( outPath ) ;
2021-04-18 18:11:47 +02:00
string uhdStr = await InterpolateUtils . UseUhd ( ) ? "--UHD" : "" ;
2021-02-16 12:14:26 +01:00
string wthreads = $"--wthreads {2 * (int)interpFactor}" ;
string rbuffer = $"--rbuffer {Config.GetInt(" rifeCudaBufferSize ", 200)}" ;
2021-03-02 22:54:30 +01:00
//string scale = $"--scale {Config.GetFloat("rifeCudaScale", 1.0f).ToStringDot()}";
2021-02-21 11:26:18 +01:00
string prec = Config . GetBool ( "rifeCudaFp16" ) ? "--fp16" : "" ;
2021-03-02 22:54:30 +01:00
string args = $" --input {inPath.Wrap()} --output {outDir} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} {uhdStr} {wthreads} {rbuffer} {prec}" ;
2021-01-26 16:45:02 +01:00
2020-11-23 16:51:05 +01:00
Process rifePy = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2021-01-18 15:32:45 +01:00
AiStarted ( rifePy , 3500 ) ;
SetProgressCheck ( Path . Combine ( Interpolate . current . tempFolder , outDir ) , interpFactor ) ;
2021-03-11 12:58:18 +01:00
rifePy . StartInfo . Arguments = $"{OSUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Networks.rifeCuda.pkgDir).Wrap()} & " +
2021-02-16 12:14:26 +01:00
$"set CUDA_VISIBLE_DEVICES={Config.Get(" torchGpus ")} & {Python.GetPyCmd()} {script} {args}" ;
2021-04-18 18:11:47 +02:00
Logger . Log ( $"Running RIFE (CUDA){(await InterpolateUtils.UseUhd() ? " ( UHD Mode ) " : " ")}..." , false ) ;
2020-11-23 16:51:05 +01:00
Logger . Log ( "cmd.exe " + rifePy . StartInfo . Arguments , true ) ;
2021-01-18 15:32:45 +01:00
2020-11-23 16:51:05 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2021-02-27 12:46:25 +01:00
rifePy . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( outLine . Data , "rife-cuda-log" ) ; } ;
2021-01-21 12:07:17 +01:00
rifePy . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "rife-cuda-log" , true ) ; } ;
2020-11-23 16:51:05 +01:00
}
2021-03-14 15:26:52 +01:00
2020-11-23 16:51:05 +01:00
rifePy . Start ( ) ;
2021-04-29 22:57:00 +02:00
2020-11-23 16:51:05 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
rifePy . BeginOutputReadLine ( ) ;
rifePy . BeginErrorReadLine ( ) ;
}
2021-01-18 15:32:45 +01:00
2020-11-26 00:07:45 +01:00
while ( ! rifePy . HasExited ) await Task . Delay ( 1 ) ;
2020-11-25 14:04:31 +01:00
}
2021-03-11 23:15:43 +01:00
public static async Task RunFlavrCuda ( string framesPath , float interpFactor , string mdl )
{
if ( Interpolate . currentlyUsingAutoEnc ) // Ensure AutoEnc is not paused
AutoEncode . paused = false ;
try
{
string flavDir = Path . Combine ( Paths . GetPkgPath ( ) , Networks . flavrCuda . pkgDir ) ;
string script = "flavr.py" ;
if ( ! File . Exists ( Path . Combine ( flavDir , script ) ) )
{
Interpolate . Cancel ( "FLAVR script not found! Make sure you didn't modify any files." ) ;
return ;
}
await RunFlavrCudaProcess ( framesPath , Paths . interpDir , script , interpFactor , mdl ) ;
if ( ! Interpolate . canceled & & Interpolate . current . alpha )
{
2021-04-22 16:15:17 +02:00
InterpolationProgress . progressPaused = true ;
2021-03-11 23:15:43 +01:00
Logger . Log ( "Interpolating alpha channel..." ) ;
await RunFlavrCudaProcess ( framesPath + Paths . alphaSuffix , Paths . interpDir + Paths . alphaSuffix , script , interpFactor , mdl ) ;
}
}
catch ( Exception e )
{
Logger . Log ( "Error running FLAVR-CUDA: " + e . Message ) ;
}
await AiFinished ( "FLAVR" ) ;
}
public static async Task RunFlavrCudaProcess ( string inPath , string outDir , string script , float interpFactor , string mdl )
{
string outPath = Path . Combine ( inPath . GetParentDir ( ) , outDir ) ;
2021-03-14 15:26:52 +01:00
Directory . CreateDirectory ( outPath ) ;
2021-03-11 23:15:43 +01:00
string args = $" --input {inPath.Wrap()} --output {outPath.Wrap()} --model {mdl}/{mdl}.pth --factor {interpFactor}" ;
Process flavrPy = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2021-03-14 15:26:52 +01:00
AiStarted ( flavrPy , 4500 ) ;
2021-03-11 23:15:43 +01:00
SetProgressCheck ( Path . Combine ( Interpolate . current . tempFolder , outDir ) , interpFactor ) ;
flavrPy . StartInfo . Arguments = $"{OSUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Networks.flavrCuda.pkgDir).Wrap()} & " +
$"set CUDA_VISIBLE_DEVICES={Config.Get(" torchGpus ")} & {Python.GetPyCmd()} {script} {args}" ;
Logger . Log ( $"Running FLAVR (CUDA)..." , false ) ;
Logger . Log ( "cmd.exe " + flavrPy . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
flavrPy . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( outLine . Data , "flavr-cuda-log" ) ; } ;
flavrPy . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "flavr-cuda-log" , true ) ; } ;
}
2021-03-14 15:26:52 +01:00
2021-03-11 23:15:43 +01:00
flavrPy . Start ( ) ;
2021-03-14 15:26:52 +01:00
2021-03-11 23:15:43 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
flavrPy . BeginOutputReadLine ( ) ;
flavrPy . BeginErrorReadLine ( ) ;
}
while ( ! flavrPy . HasExited ) await Task . Delay ( 1 ) ;
}
2021-01-18 15:32:45 +01:00
public static async Task RunRifeNcnn ( string framesPath , string outPath , int factor , string mdl )
2020-11-26 00:07:45 +01:00
{
processTimeMulti . Restart ( ) ;
2021-03-01 18:13:19 +01:00
try
{
2021-04-18 18:11:47 +02:00
Logger . Log ( $"Running RIFE (NCNN){(await InterpolateUtils.UseUhd() ? " ( UHD Mode ) " : " ")}..." , false ) ;
2021-03-01 18:13:19 +01:00
await RunRifeNcnnMulti ( framesPath , outPath , factor , mdl ) ;
2021-01-27 14:29:49 +01:00
2021-03-01 18:13:19 +01:00
if ( ! Interpolate . canceled & & Interpolate . current . alpha )
{
2021-04-22 16:15:17 +02:00
InterpolationProgress . progressPaused = true ;
2021-03-01 18:13:19 +01:00
Logger . Log ( "Interpolating alpha channel..." ) ;
await RunRifeNcnnMulti ( framesPath + Paths . alphaSuffix , outPath + Paths . alphaSuffix , factor , mdl ) ;
}
}
catch ( Exception e )
2021-01-27 14:29:49 +01:00
{
2021-03-01 18:13:19 +01:00
Logger . Log ( "Error running RIFE-NCNN: " + e . Message ) ;
2021-01-27 14:29:49 +01:00
}
2021-02-11 21:05:45 +01:00
await AiFinished ( "RIFE" ) ;
2021-01-27 14:29:49 +01:00
}
static async Task RunRifeNcnnMulti ( string framesPath , string outPath , int factor , string mdl )
{
int times = ( int ) Math . Log ( factor , 2 ) ;
if ( times > 1 )
2020-12-04 16:53:39 +01:00
AutoEncode . paused = true ; // Disable autoenc until the last iteration
2021-02-09 18:23:22 +01:00
else
AutoEncode . paused = false ;
2020-12-04 16:53:39 +01:00
2021-01-27 14:29:49 +01:00
for ( int iteration = 1 ; iteration < = times ; iteration + + )
2020-11-26 00:07:45 +01:00
{
if ( Interpolate . canceled ) return ;
2021-01-27 12:04:22 +01:00
if ( Interpolate . currentlyUsingAutoEnc & & iteration = = times ) // Enable autoenc if this is the last iteration
2020-12-04 16:53:39 +01:00
AutoEncode . paused = false ;
2020-11-26 00:07:45 +01:00
2021-01-27 12:04:22 +01:00
if ( iteration > 1 )
{
Logger . Log ( $"Re-Running RIFE for {Math.Pow(2, iteration)}x interpolation..." , false ) ;
string lastInterpPath = outPath + $"-run{iteration - 1}" ;
Directory . Move ( outPath , lastInterpPath ) ; // Rename last interp folder
await RunRifeNcnnProcess ( lastInterpPath , outPath , mdl ) ;
2021-05-09 18:31:39 +02:00
await IOUtils . TryDeleteIfExistsAsync ( lastInterpPath ) ;
2021-01-27 12:04:22 +01:00
}
else
{
await RunRifeNcnnProcess ( framesPath , outPath , mdl ) ;
}
2020-11-26 00:07:45 +01:00
}
}
2021-01-18 15:32:45 +01:00
static async Task RunRifeNcnnProcess ( string inPath , string outPath , string mdl )
2020-11-26 00:07:45 +01:00
{
2021-01-27 14:29:49 +01:00
Directory . CreateDirectory ( outPath ) ;
2020-11-26 00:07:45 +01:00
Process rifeNcnn = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
2021-01-18 15:32:45 +01:00
AiStarted ( rifeNcnn , 1500 , inPath ) ;
SetProgressCheck ( outPath , 2 ) ;
2021-01-05 17:23:37 +01:00
2021-04-18 18:11:47 +02:00
string uhdStr = await InterpolateUtils . UseUhd ( ) ? "-u" : "" ;
2021-01-20 20:24:46 +01:00
string ttaStr = Config . GetBool ( "rifeNcnnUseTta" , false ) ? "-x" : "" ;
2021-01-05 17:23:37 +01:00
2021-02-10 23:16:04 +01:00
string oldMdlName = mdl ;
mdl = RifeNcnn2Workaround ( mdl ) ; // TODO: REMOVE ONCE NIHUI HAS GOTTEN RID OF THE SHITTY HARDCODED VERSION CHECK
2021-03-11 12:58:18 +01:00
rifeNcnn . StartInfo . Arguments = $"{OSUtils.GetCmdArg()} cd /D {Path.Combine(Paths.GetPkgPath(), Networks.rifeNcnn.pkgDir).Wrap()} & rife-ncnn-vulkan.exe " +
2021-01-21 11:39:08 +01:00
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl.ToLower()} {ttaStr} {uhdStr} -g {Config.Get(" ncnnGpus ")} -f {GetNcnnPattern()} -j {GetNcnnThreads()}" ;
2021-01-05 17:23:37 +01:00
2020-11-26 00:07:45 +01:00
Logger . Log ( "cmd.exe " + rifeNcnn . StartInfo . Arguments , true ) ;
2021-01-05 17:23:37 +01:00
2020-11-26 00:07:45 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
2020-12-27 22:52:14 +01:00
rifeNcnn . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "rife-ncnn-log" ) ; } ;
2021-01-21 12:07:17 +01:00
rifeNcnn . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "rife-ncnn-log" , true ) ; } ;
2020-11-26 00:07:45 +01:00
}
2021-01-05 17:23:37 +01:00
2020-11-26 00:07:45 +01:00
rifeNcnn . Start ( ) ;
2021-01-05 17:23:37 +01:00
2020-11-26 00:07:45 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
rifeNcnn . BeginOutputReadLine ( ) ;
rifeNcnn . BeginErrorReadLine ( ) ;
}
2021-01-05 17:23:37 +01:00
2020-11-26 00:07:45 +01:00
while ( ! rifeNcnn . HasExited ) await Task . Delay ( 1 ) ;
2021-02-10 23:16:04 +01:00
RifeNcnn2Workaround ( oldMdlName , true ) ;
2020-11-26 00:07:45 +01:00
}
2021-02-01 18:05:50 +01:00
public static async Task RunDainNcnn ( string framesPath , string outPath , float factor , string mdl , int tilesize )
2021-01-27 14:20:27 +01:00
{
2021-02-09 18:23:22 +01:00
if ( Interpolate . currentlyUsingAutoEnc ) // Ensure AutoEnc is not paused
AutoEncode . paused = false ;
2021-03-01 18:13:19 +01:00
try
{
await RunDainNcnnProcess ( framesPath , outPath , factor , mdl , tilesize ) ;
2021-01-27 14:20:27 +01:00
2021-03-01 18:13:19 +01:00
if ( ! Interpolate . canceled & & Interpolate . current . alpha )
{
2021-04-22 16:15:17 +02:00
InterpolationProgress . progressPaused = true ;
2021-03-01 18:13:19 +01:00
Logger . Log ( "Interpolating alpha channel..." ) ;
await RunDainNcnnProcess ( framesPath + Paths . alphaSuffix , outPath + Paths . alphaSuffix , factor , mdl , tilesize ) ;
}
}
catch ( Exception e )
2021-01-27 14:20:27 +01:00
{
2021-03-01 18:13:19 +01:00
Logger . Log ( "Error running DAIN-NCNN: " + e . Message ) ;
2021-01-27 14:20:27 +01:00
}
2021-02-11 21:05:45 +01:00
await AiFinished ( "DAIN" ) ;
2021-01-27 14:20:27 +01:00
}
2021-02-01 18:05:50 +01:00
public static async Task RunDainNcnnProcess ( string framesPath , string outPath , float factor , string mdl , int tilesize )
2021-01-21 11:39:08 +01:00
{
2021-03-11 12:58:18 +01:00
string dainDir = Path . Combine ( Paths . GetPkgPath ( ) , Networks . dainNcnn . pkgDir ) ;
2021-01-27 14:20:27 +01:00
Directory . CreateDirectory ( outPath ) ;
2021-01-21 11:39:08 +01:00
Process dain = OSUtils . NewProcess ( ! OSUtils . ShowHiddenCmd ( ) ) ;
AiStarted ( dain , 1500 ) ;
SetProgressCheck ( outPath , factor ) ;
2021-04-22 16:15:17 +02:00
int targetFrames = ( ( IOUtils . GetAmountOfFiles ( lastInPath , false , "*.*" ) * factor ) . RoundToInt ( ) ) - ( factor . RoundToInt ( ) - 1 ) ; // TODO: Won't work with fractional factors
2021-01-21 11:39:08 +01:00
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.ToLower()}" +
$" -t {GetNcnnTilesize(tilesize)} -g {Config.Get(" ncnnGpus ")} -f {GetNcnnPattern()} -j 2:1:2" ;
dain . StartInfo . Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}" ;
Logger . Log ( "Running DAIN..." , false ) ;
Logger . Log ( "cmd.exe " + dain . StartInfo . Arguments , true ) ;
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
dain . OutputDataReceived + = ( sender , outLine ) = > { LogOutput ( "[O] " + outLine . Data , "dain-ncnn-log" ) ; } ;
2021-01-21 12:07:17 +01:00
dain . ErrorDataReceived + = ( sender , outLine ) = > { LogOutput ( "[E] " + outLine . Data , "dain-ncnn-log" , true ) ; } ;
2021-01-21 11:39:08 +01:00
}
dain . Start ( ) ;
2021-02-16 12:14:26 +01:00
2021-01-21 11:39:08 +01:00
if ( ! OSUtils . ShowHiddenCmd ( ) )
{
dain . BeginOutputReadLine ( ) ;
dain . BeginErrorReadLine ( ) ;
}
while ( ! dain . HasExited )
2021-01-27 12:04:22 +01:00
await Task . Delay ( 100 ) ;
2021-01-21 11:39:08 +01:00
}
2021-01-21 12:07:17 +01:00
static void LogOutput ( string line , string logFilename , bool err = false )
2020-11-23 16:51:05 +01:00
{
2020-12-09 14:32:43 +01:00
if ( string . IsNullOrWhiteSpace ( line ) | | line . Length < 6 )
2020-11-23 16:51:05 +01:00
return ;
2021-02-27 12:46:25 +01:00
Stopwatch sw = new Stopwatch ( ) ;
sw . Restart ( ) ;
if ( line . Contains ( "iVBOR" ) )
{
try
{
string [ ] split = line . Split ( ':' ) ;
//MemoryStream stream = new MemoryStream(Convert.FromBase64String(split[1]));
//Image img = Image.FromStream(stream);
Logger . Log ( $"Received image {split[0]} in {sw.ElapsedMilliseconds} ms" , true ) ;
}
catch ( Exception e )
{
Logger . Log ( $"Failed to decode b64 string - {e}:" ) ;
Logger . Log ( line ) ;
}
return ;
}
2021-04-25 21:12:45 +02:00
Logger . Log ( line , true , false , logFilename ) ;
2020-11-23 16:51:05 +01:00
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!" ) ;
2021-01-21 12:07:17 +01:00
if ( ! hasShownError & & err & & line . ToLower ( ) . Contains ( "out of memory" ) )
2020-11-24 12:28:47 +01:00
{
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" ) ;
}
2021-01-21 12:07:17 +01:00
if ( ! hasShownError & & err & & line . ToLower ( ) . Contains ( "modulenotfounderror" ) )
2020-11-24 12:28:47 +01:00
{
hasShownError = true ;
2021-01-21 12:07:17 +01:00
InterpolateUtils . ShowMessage ( $"A python module is missing.\nCheck {logFilename} for details.\n\n{line}" , "Error" ) ;
2021-01-04 14:27:34 +01:00
if ( ! Python . HasEmbeddedPyFolder ( ) )
2021-02-09 16:07:57 +01:00
Process . Start ( "https://github.com/n00mkrad/flowframes/blob/main/PythonDependencies.md" ) ;
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-26 20:17:18 +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
}
2021-04-12 15:40:05 +02:00
if ( ! hasShownError & & line . ToLower ( ) . Contains ( "illegal memory access" ) )
{
hasShownError = true ;
InterpolateUtils . ShowMessage ( $"Your GPU appears to be unstable! If you have an overclock enabled, please disable it!\n\n{line}" , "Error" ) ;
}
if ( ! hasShownError & & line . ToLower ( ) . Contains ( "error(s) in loading state_dict" ) )
{
hasShownError = true ;
string msg = ( Interpolate . current . ai . aiName = = Networks . flavrCuda . aiName ) ? "\n\nFor FLAVR, you need to select the correct model for each scale!" : "" ;
InterpolateUtils . ShowMessage ( $"Error loading the AI model!\n\n{line}{msg}" , "Error" ) ;
}
2021-01-21 12:07:17 +01:00
if ( ! hasShownError & & err & & ( line . Contains ( "RuntimeError" ) | | line . Contains ( "ImportError" ) | | line . Contains ( "OSError" ) ) )
2020-11-24 12:28:47 +01:00
{
hasShownError = true ;
2020-12-07 22:10:58 +01:00
InterpolateUtils . ShowMessage ( $"A python error occured during interpolation!\nCheck {logFilename} for details.\n\n{line}" , "Error" ) ;
2020-11-24 12:28:47 +01:00
}
2020-11-26 20:17:18 +01:00
2021-05-11 12:08:01 +02:00
if ( ! hasShownError & & err & & line . MatchesWildcard ( "vk*Instance* failed" ) )
2020-11-26 20:17:18 +01:00
{
hasShownError = true ;
2021-05-11 12:08:01 +02:00
InterpolateUtils . ShowMessage ( $"Vulkan failed to start up!\n\n{line}\n\nThis most likely means your GPU is not compatible." , "Error" ) ;
2020-11-26 20:17:18 +01:00
}
2021-01-21 12:07:17 +01:00
if ( ! hasShownError & & err & & line . Contains ( "vkAllocateMemory failed" ) )
{
hasShownError = true ;
bool usingDain = ( Interpolate . current . ai . aiName = = Networks . dainNcnn . aiName ) ;
string msg = usingDain ? "\n\nTry reducing the tile size in the AI settings." : "Try a lower resolution (Settings -> Max Video Size)." ;
InterpolateUtils . ShowMessage ( $"Vulkan ran out of memory!\n\n{line}{msg}" , "Error" ) ;
}
2021-05-11 12:08:01 +02:00
if ( ! hasShownError & & err & & line . Contains ( "invalid gpu device" ) )
2021-05-04 14:39:11 +02:00
{
hasShownError = true ;
2021-05-11 12:08:01 +02:00
InterpolateUtils . ShowMessage ( $"A Vulkan error occured during interpolation!\n\n{line}\n\nAre your GPU IDs set correctly?" , "Error" ) ;
2021-05-04 14:39:11 +02:00
}
2021-05-11 12:08:01 +02:00
if ( ! hasShownError & & err & & line . MatchesWildcard ( "vk* failed" ) )
2020-12-10 16:46:30 +01:00
{
hasShownError = true ;
2021-05-11 12:08:01 +02:00
InterpolateUtils . ShowMessage ( $"A Vulkan error occured during interpolation!\n\n{line}" , "Error" ) ;
2020-12-10 16:46:30 +01:00
}
2020-11-26 20:17:18 +01:00
if ( hasShownError )
Interpolate . Cancel ( ) ;
2021-02-11 09:05:10 +01:00
2021-04-22 16:15:17 +02:00
InterpolationProgress . UpdateLastFrameFromInterpOutput ( line ) ;
2020-11-23 16:51:05 +01:00
}
2020-12-10 16:10:52 +01:00
2021-01-21 11:39:08 +01:00
static string GetNcnnPattern ( )
{
2021-04-22 16:15:17 +02:00
return $"%0{Padding.interpFrames}d{Interpolate.current.interpExt}" ;
2021-01-21 11:39:08 +01:00
}
2020-12-10 16:10:52 +01:00
static string GetNcnnTilesize ( int tilesize )
{
int gpusAmount = Config . Get ( "ncnnGpus" ) . Split ( ',' ) . Length ;
string tilesizeStr = $"{tilesize}" ;
for ( int i = 1 ; i < gpusAmount ; i + + )
tilesizeStr + = $",{tilesize}" ;
return tilesizeStr ;
}
static string GetNcnnThreads ( )
{
int gpusAmount = Config . Get ( "ncnnGpus" ) . Split ( ',' ) . Length ;
int procThreads = Config . GetInt ( "ncnnThreads" ) ;
string progThreadsStr = $"{procThreads}" ;
for ( int i = 1 ; i < gpusAmount ; i + + )
progThreadsStr + = $",{procThreads}" ;
return $"4:{progThreadsStr}:4" ; ;
}
2021-02-10 23:16:04 +01:00
static string RifeNcnn2Workaround ( string modelName , bool reset = false )
{
2021-02-27 12:46:25 +01:00
if ( ! modelName . StartsWith ( "RIFE2" ) ) return modelName ;
2021-02-10 23:16:04 +01:00
string validMdlName = "rife-v2" ;
2021-03-11 12:58:18 +01:00
string rifeFolderPath = Path . Combine ( Paths . GetPkgPath ( ) , Networks . rifeNcnn . pkgDir ) ;
2021-02-10 23:16:04 +01:00
string modelFolderPath = Path . Combine ( rifeFolderPath , modelName ) ;
string fixedModelFolderPath = Path . Combine ( rifeFolderPath , validMdlName ) ;
if ( ! reset )
{
IOUtils . TryDeleteIfExists ( fixedModelFolderPath ) ;
Directory . Move ( modelFolderPath , fixedModelFolderPath ) ;
}
else
{
IOUtils . TryDeleteIfExists ( modelFolderPath ) ;
Directory . Move ( fixedModelFolderPath , modelFolderPath ) ;
}
return validMdlName ;
}
2020-11-23 16:51:05 +01:00
}
}