2020-11-29 16:10:31 +01:00
using Flowframes.Data ;
using Flowframes.IO ;
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
namespace Flowframes.Main
{
using static Interpolate ;
class InterpolateSteps
{
public enum Step { ExtractScnChanges , ExtractFrames , Interpolate , CreateVid , Reset }
public static string currentInPath ;
public static string currentOutPath ;
public static string currentInterpFramesDir ;
public static AI currentAi ;
public static OutMode currentOutMode ;
public static async Task Run ( string step )
{
canceled = false ;
Program . mainForm . SetWorking ( true ) ;
InitState ( ) ;
2020-12-02 23:11:27 +01:00
if ( ! InterpolateUtils . InputIsValid ( currentInPath , currentOutPath , currentOutFps , interpFactor , Program . mainForm . GetTilesize ( ) ) ) return ; // General input checks
2020-11-29 16:10:31 +01:00
if ( step . Contains ( "Extract Scene Changes" ) )
2020-12-02 14:36:41 +01:00
{
if ( ! currentInputIsFrames ) // Input is video - extract frames first
await ExtractSceneChanges ( ) ;
else
InterpolateUtils . ShowMessage ( "Scene changes can only be extracted from videos, not frames!" , "Error" ) ;
}
2020-11-29 16:10:31 +01:00
if ( step . Contains ( "Extract Video Frames" ) )
2020-12-02 14:36:41 +01:00
{
if ( ! currentInputIsFrames ) // Input is video - extract frames first
await ExtractVideoFrames ( ) ;
else
await FFmpegCommands . ImportImages ( currentInPath , currentFramesPath ) ;
}
2020-11-29 16:10:31 +01:00
if ( step . Contains ( "Run Interpolation" ) )
await DoInterpolate ( ) ;
2020-12-02 14:36:41 +01:00
2020-11-29 16:10:31 +01:00
if ( step . Contains ( "Create Output Video" ) )
await CreateOutputVid ( ) ;
2020-12-02 14:36:41 +01:00
2020-11-29 16:10:31 +01:00
if ( step . Contains ( "Cleanup" ) )
await Reset ( ) ;
Program . mainForm . SetWorking ( false ) ;
Logger . Log ( "Done running this step." ) ;
}
2020-12-02 23:11:27 +01:00
static void InitState ( )
2020-11-29 16:10:31 +01:00
{
BatchEntry e = Program . mainForm . GetBatchEntry ( ) ;
interpFactor = e . interpFactor ;
currentAi = e . ai ;
2020-12-02 23:11:27 +01:00
try
{
2020-11-29 16:10:31 +01:00
currentInPath = e . inPath ;
currentOutPath = e . outPath ;
currentTempDir = InterpolateUtils . GetTempFolderLoc ( currentInPath , currentOutPath ) ;
2020-11-30 20:32:33 +01:00
currentFramesPath = Path . Combine ( currentTempDir , Paths . framesDir ) ;
2020-12-01 16:54:12 +01:00
2020-12-02 23:11:27 +01:00
currentInterpFramesDir = Path . Combine ( currentTempDir , Paths . interpDir ) ;
2020-12-02 14:36:41 +01:00
2020-12-02 23:11:27 +01:00
currentInputIsFrames = IOUtils . IsPathDirectory ( currentInPath ) ;
}
catch
{
// Handled later basically
}
2020-11-29 16:10:31 +01:00
}
2020-12-02 23:11:27 +01:00
public static async Task ExtractSceneChanges ( )
2020-11-29 16:10:31 +01:00
{
2020-12-02 00:44:43 +01:00
string scenesPath = Path . Combine ( currentTempDir , Paths . scenesDir ) ;
if ( ! IOUtils . TryDeleteIfExists ( scenesPath ) )
{
InterpolateUtils . ShowMessage ( "Failed to delete existing scenes folder - Make sure no file is opened in another program!" , "Error" ) ;
return ;
}
2020-11-29 16:10:31 +01:00
Program . mainForm . SetStatus ( "Extracting scenes from video..." ) ;
2020-12-02 00:44:43 +01:00
await FFmpegCommands . ExtractSceneChanges ( currentInPath , scenesPath ) ;
2020-11-29 16:10:31 +01:00
await Task . Delay ( 10 ) ;
}
2020-12-02 23:11:27 +01:00
public static async Task ExtractVideoFrames ( )
2020-11-29 16:10:31 +01:00
{
2020-11-30 20:32:33 +01:00
currentFramesPath = Path . Combine ( currentTempDir , Paths . framesDir ) ;
2020-12-02 00:44:43 +01:00
if ( ! IOUtils . TryDeleteIfExists ( currentFramesPath ) )
{
InterpolateUtils . ShowMessage ( "Failed to delete existing frames folder - Make sure no file is opened in another program!" , "Error" ) ;
return ;
}
2020-11-29 16:10:31 +01:00
bool extractAudio = true ;
Program . mainForm . SetStatus ( "Extracting frames from video..." ) ;
Size resolution = IOUtils . GetVideoRes ( currentInPath ) ;
int maxHeight = Config . GetInt ( "maxVidHeight" ) ;
if ( resolution . Height > maxHeight )
{
float factor = ( float ) maxHeight / resolution . Height ;
int width = ( resolution . Width * factor ) . RoundToInt ( ) ;
Logger . Log ( $"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}." ) ;
await FFmpegCommands . VideoToFrames ( currentInPath , currentFramesPath , Config . GetInt ( "dedupMode" ) = = 2 , false , new Size ( width , maxHeight ) ) ;
}
else
{
await FFmpegCommands . VideoToFrames ( currentInPath , currentFramesPath , Config . GetInt ( "dedupMode" ) = = 2 , false ) ;
}
if ( extractAudio )
{
string audioFile = Path . Combine ( currentTempDir , "audio.m4a" ) ;
if ( audioFile ! = null & & ! File . Exists ( audioFile ) )
await FFmpegCommands . ExtractAudio ( currentInPath , audioFile ) ;
}
if ( ! canceled & & Config . GetBool ( "enableLoop" ) & & Config . GetInt ( "timingMode" ) ! = 1 )
{
2020-12-02 17:23:24 +01:00
string lastFrame = IOUtils . GetHighestFrameNumPath ( currentFramesPath ) ;
2020-11-29 16:10:31 +01:00
int newNum = Path . GetFileName ( lastFrame ) . GetInt ( ) + 1 ;
2020-12-02 17:23:24 +01:00
string newFilename = Path . Combine ( lastFrame . GetParentDir ( ) , newNum . ToString ( ) . PadLeft ( Padding . inputFrames , '0' ) + ".png" ) ;
string firstFrame = new DirectoryInfo ( currentFramesPath ) . GetFiles ( "*.png" ) [ 0 ] . FullName ;
2020-11-29 16:10:31 +01:00
File . Copy ( firstFrame , newFilename ) ;
Logger . Log ( "Copied loop frame." ) ;
}
}
2020-12-02 23:11:27 +01:00
public static async Task DoInterpolate ( )
2020-11-29 16:10:31 +01:00
{
2020-12-02 01:09:41 +01:00
currentFramesPath = Path . Combine ( currentTempDir , Paths . framesDir ) ;
2020-12-02 00:44:43 +01:00
if ( ! Directory . Exists ( currentFramesPath ) )
{
InterpolateUtils . ShowMessage ( "There are no extracted frames that can be interpolated!\nDid you run the extraction step?" , "Error" ) ;
return ;
}
if ( ! IOUtils . TryDeleteIfExists ( currentInterpFramesDir ) )
{
InterpolateUtils . ShowMessage ( "Failed to delete existing frames folder - Make sure no file is opened in another program!" , "Error" ) ;
return ;
}
2020-12-01 16:54:12 +01:00
foreach ( string ini in Directory . GetFiles ( currentTempDir , "*.ini" , SearchOption . TopDirectoryOnly ) )
IOUtils . TryDeleteIfExists ( ini ) ;
2020-12-02 00:44:43 +01:00
IOUtils . ReverseRenaming ( AiProcess . filenameMap , true ) ; // Get timestamps back
2020-11-30 20:52:43 +01:00
await PostProcessFrames ( true ) ;
2020-11-29 16:10:31 +01:00
lastInterpFactor = interpFactor ;
int frames = IOUtils . GetAmountOfFiles ( currentFramesPath , false , "*.png" ) ;
int targetFrameCount = frames * lastInterpFactor ;
2020-12-02 00:44:43 +01:00
GetProgressByFrameAmount ( currentInterpFramesDir , targetFrameCount ) ;
2020-11-29 16:10:31 +01:00
if ( canceled ) return ;
Program . mainForm . SetStatus ( "Running AI..." ) ;
int tilesize = currentAi . supportsTiling ? Config . GetInt ( $"tilesize_{currentAi.aiName}" ) : 512 ;
2020-12-02 00:44:43 +01:00
await RunAi ( currentInterpFramesDir , targetFrameCount , tilesize , currentAi ) ;
2020-11-29 16:10:31 +01:00
Program . mainForm . SetProgress ( 0 ) ;
}
2020-12-02 23:11:27 +01:00
public static async Task CreateOutputVid ( )
2020-11-29 16:10:31 +01:00
{
2020-12-02 15:34:59 +01:00
currentOutMode = Program . mainForm . GetBatchEntry ( ) . outMode ;
2020-11-29 16:10:31 +01:00
string outPath = Path . Combine ( currentOutPath , Path . GetFileNameWithoutExtension ( currentInPath ) + IOUtils . GetAiSuffix ( currentAi , lastInterpFactor ) + InterpolateUtils . GetExt ( currentOutMode ) ) ;
2020-12-02 15:34:59 +01:00
await CreateVideo . Export ( currentInterpFramesDir , outPath , currentOutMode ) ;
2020-11-29 16:10:31 +01:00
}
2020-12-02 23:11:27 +01:00
public static async Task Reset ( )
2020-11-29 16:10:31 +01:00
{
2020-12-02 00:44:43 +01:00
Cleanup ( currentInterpFramesDir , true ) ;
2020-11-29 16:10:31 +01:00
}
}
}