2021-08-23 16:50:18 +02:00
using Flowframes.Media ;
using Flowframes.IO ;
using Flowframes.Magick ;
using Flowframes.Main ;
using Flowframes.Os ;
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using System.Windows.Forms ;
using Flowframes.Data ;
2023-12-21 19:06:31 +01:00
using Flowframes.MiscUtils ;
2021-08-23 16:50:18 +02:00
namespace Flowframes.Ui
{
class MainUiFunctions
{
public static async Task InitInput ( TextBox outputTbox , TextBox inputTbox , TextBox fpsInTbox , bool start = false )
{
2022-07-20 21:48:30 +02:00
2023-02-15 18:25:41 +01:00
Program . mainForm . SetTab ( Program . mainForm . interpOptsTab . Name ) ;
2021-08-23 16:50:18 +02:00
Program . mainForm . ResetInputInfo ( ) ;
string path = inputTbox . Text . Trim ( ) ;
2022-04-05 18:07:05 +02:00
GetFrameCountCached . Clear ( ) ;
GetMediaResolutionCached . Clear ( ) ;
2021-08-23 16:50:18 +02:00
if ( Config . GetBool ( Config . Key . clearLogOnInput ) )
Logger . ClearLogBox ( ) ;
2021-12-06 22:46:39 +01:00
SetOutPath ( outputTbox , inputTbox . Text . Trim ( ) . GetParentDir ( ) ) ;
2021-08-23 16:50:18 +02:00
Program . lastInputPath = path ;
Program . lastInputPathIsSsd = OsUtils . DriveIsSSD ( path ) ;
if ( ! Program . lastInputPathIsSsd )
Logger . Log ( "Your file seems to be on an HDD or USB device. It is recommended to interpolate videos on an SSD drive for best performance." ) ;
2022-07-19 21:30:10 +02:00
Logger . Log ( "Importing file..." ) ;
2022-07-20 18:10:31 +02:00
Interpolate . currentMediaFile = new MediaFile ( path ) ;
await Interpolate . currentMediaFile . Initialize ( ) ;
Program . mainForm . currInDuration = Interpolate . currentMediaFile . DurationMs ;
2021-08-23 16:50:18 +02:00
Program . mainForm . currInDurationCut = Program . mainForm . currInDuration ;
2022-07-27 14:10:29 +02:00
Fraction fps = Interpolate . currentMediaFile . VideoStreams . Count > 0 ? Interpolate . currentMediaFile . VideoStreams [ 0 ] . Rate : new Fraction ( ) ;
2023-12-21 19:06:31 +01:00
string fpsStr = fps . GetFloat ( ) > 0 ? FormatUtils . Fraction ( fps ) : "Not Found" ;
2021-08-23 16:50:18 +02:00
Program . mainForm . currInFpsDetected = fps ;
fpsInTbox . Text = fps . GetString ( ) ;
2022-07-20 18:10:31 +02:00
Logger . Log ( $"Video FPS: {fpsStr} - Total Number Of Frames: {Interpolate.currentMediaFile.FrameCount}" , false , true ) ;
2021-08-23 16:50:18 +02:00
Program . mainForm . GetInputFpsTextbox ( ) . ReadOnly = ( fps . GetFloat ( ) > 0 & & ! Config . GetBool ( "allowCustomInputRate" , false ) ) ;
Program . mainForm . currInFps = fps ;
2022-07-20 18:10:31 +02:00
Program . mainForm . currInFrames = Interpolate . currentMediaFile . FrameCount ;
2021-08-23 16:50:18 +02:00
Program . mainForm . UpdateInputInfo ( ) ;
CheckExistingFolder ( path , outputTbox . Text . Trim ( ) ) ;
await Task . Delay ( 10 ) ;
await PrintResolution ( path ) ;
await Task . Delay ( 10 ) ;
InterpolationProgress . SetPreviewImg ( await GetThumbnail ( path ) ) ;
2021-09-30 19:57:59 +02:00
if ( AutoEncodeResume . resumeNextRun )
Logger . Log ( $"Incomplete interpolation detected. Flowframes will resume the interpolation." ) ;
2021-08-23 16:50:18 +02:00
if ( start )
Program . mainForm . runBtn_Click ( null , null ) ;
}
2021-12-06 12:48:49 +01:00
public static bool SetOutPath ( TextBox outputTbox , string outPath )
{
bool customOutDir = Config . GetInt ( "outFolderLoc" ) = = 1 ;
outputTbox . Text = customOutDir ? Config . Get ( "custOutDir" ) . Trim ( ) : outPath ;
if ( customOutDir )
{
try
{
Directory . CreateDirectory ( outputTbox . Text ) ;
}
catch ( Exception e )
{
Logger . Log ( $"Failed to create output folder: {e.Message}" ) ;
outputTbox . Text = outPath ;
return false ;
}
}
return true ;
}
2021-08-23 16:50:18 +02:00
static void CheckExistingFolder ( string inpath , string outpath )
{
2022-07-20 18:10:31 +02:00
if ( Interpolate . currentSettings = = null | | ! Interpolate . currentSettings . stepByStep ) return ;
2021-08-23 16:50:18 +02:00
string tmpFolder = InterpolateUtils . GetTempFolderLoc ( inpath , outpath ) ;
2022-07-25 10:37:44 +02:00
2021-08-23 16:50:18 +02:00
if ( Directory . Exists ( tmpFolder ) )
{
2022-07-20 18:10:31 +02:00
int scnFrmAmount = IoUtils . GetAmountOfFiles ( Path . Combine ( tmpFolder , Paths . scenesDir ) , false , "*" + Interpolate . currentSettings . interpExt ) ; // TODO: Make this work if the frames extension was changed
2021-08-23 16:50:18 +02:00
string scnFrames = scnFrmAmount > 0 ? $"{scnFrmAmount} scene frames" : "no scene frames" ;
2022-07-20 18:10:31 +02:00
int srcFrmAmount = IoUtils . GetAmountOfFiles ( Path . Combine ( tmpFolder , Paths . framesDir ) , false , "*" + Interpolate . currentSettings . interpExt ) ;
2021-08-23 16:50:18 +02:00
string srcFrames = srcFrmAmount > 1 ? $"{srcFrmAmount} source frames" : "no source frames" ;
int interpFrmAmount = IoUtils . GetAmountOfFiles ( Path . Combine ( tmpFolder , Paths . interpDir ) , false ) ;
string interpFrames = interpFrmAmount > 2 ? $"{interpFrmAmount} interpolated frames" : "no interpolated frames" ;
string msg = $"A temporary folder for this video already exists. It contains {scnFrames}, {srcFrames}, {interpFrames}." ;
2022-07-24 22:30:30 +02:00
DialogResult dialogResult = UiUtils . ShowMessageBox ( $"{msg}\n\nClick \" Yes \ " to use the existing files or \"No\" to delete them." , "Use files from existing temp folder?" , MessageBoxButtons . YesNo ) ;
2022-07-25 10:37:44 +02:00
2021-08-23 16:50:18 +02:00
if ( dialogResult = = DialogResult . No )
{
IoUtils . TryDeleteIfExists ( tmpFolder ) ;
Logger . Log ( "Deleted old temp folder." ) ;
}
}
}
static async Task PrintResolution ( string path )
{
Size res = new Size ( ) ;
2022-07-20 18:10:31 +02:00
if ( path = = Interpolate . currentSettings ? . inPath )
res = Interpolate . currentSettings . InputResolution ;
2021-08-23 16:50:18 +02:00
else
res = await GetMediaResolutionCached . GetSizeAsync ( path ) ;
if ( res . Width > 1 & & res . Height > 1 )
Logger . Log ( $"Input Resolution: {res.Width}x{res.Height}" ) ;
Program . mainForm . currInRes = res ;
Program . mainForm . UpdateInputInfo ( ) ;
}
public static async Task < Image > GetThumbnail ( string path )
{
2022-07-27 14:10:29 +02:00
string imgOnDisk = Path . Combine ( Paths . GetSessionDataPath ( ) , "thumb-temp.jpg" ) ;
2021-09-08 18:14:56 +02:00
2021-08-23 16:50:18 +02:00
try
{
if ( ! IoUtils . IsPathDirectory ( path ) ) // If path is video - Extract first frame
{
await FfmpegExtract . ExtractSingleFrame ( path , imgOnDisk , 1 ) ;
return IoUtils . GetImage ( imgOnDisk ) ;
}
else // Path is frame folder - Get first frame
{
return IoUtils . GetImage ( IoUtils . GetFilesSorted ( path ) [ 0 ] ) ;
}
}
catch ( Exception e )
{
Logger . Log ( "GetThumbnail Error: " + e . Message , true ) ;
return null ;
}
}
2021-08-24 15:43:29 +02:00
2022-04-05 23:22:09 +02:00
public static float ValidateInterpFactor ( float factor )
2021-08-24 15:43:29 +02:00
{
AI ai = Program . mainForm . GetAi ( ) ;
2022-07-27 15:18:37 +02:00
if ( ai . NameInternal = = Implementations . rifeNcnn . NameInternal & & ! Program . mainForm . GetModel ( ai ) . Dir . Contains ( "v4" ) )
2022-04-17 18:39:32 +02:00
{
if ( factor ! = 2 )
2022-05-31 22:17:22 +02:00
Logger . Log ( $"{ai.FriendlyName} models before 4.0 only support 2x interpolation!" ) ;
2022-04-17 18:39:32 +02:00
return 2 ;
}
2022-05-31 22:17:22 +02:00
if ( ai . FactorSupport = = AI . InterpFactorSupport . Fixed )
2022-04-06 20:48:47 +02:00
{
2022-05-31 22:17:22 +02:00
int closest = ai . SupportedFactors . Min ( i = > ( Math . Abs ( factor . RoundToInt ( ) - i ) , i ) ) . i ;
2022-04-06 20:48:47 +02:00
return ( float ) closest ;
}
2022-05-31 22:17:22 +02:00
if ( ai . FactorSupport = = AI . InterpFactorSupport . AnyPowerOfTwo )
2022-04-06 20:48:47 +02:00
{
return ToNearestPow2 ( factor . RoundToInt ( ) ) . Clamp ( 2 , 128 ) ;
}
2022-05-31 22:17:22 +02:00
if ( ai . FactorSupport = = AI . InterpFactorSupport . AnyInteger )
2022-04-06 20:48:47 +02:00
{
return factor . RoundToInt ( ) . Clamp ( 2 , 128 ) ;
}
2022-05-31 22:17:22 +02:00
if ( ai . FactorSupport = = AI . InterpFactorSupport . AnyFloat )
2022-04-06 20:48:47 +02:00
{
return factor . Clamp ( 2 , 128 ) ;
}
2021-08-24 15:43:29 +02:00
return factor ;
}
static bool IsPowerOfTwo ( int x )
{
return ( x ! = 0 ) & & ( ( x & ( x - 1 ) ) = = 0 ) ;
}
2022-04-06 20:48:47 +02:00
static int ToNearestPow2 ( int x )
{
int next = ToNextNearestPow2 ( x ) ;
int prev = next > > 1 ;
return next - x < x - prev ? next : prev ;
}
static int ToNextNearestPow2 ( int x )
{
if ( x < 0 ) { return 0 ; }
- - x ;
x | = x > > 1 ;
x | = x > > 2 ;
x | = x > > 4 ;
x | = x > > 8 ;
x | = x > > 16 ;
return x + 1 ;
}
2021-08-23 16:50:18 +02:00
}
}