2021-02-02 12:56:48 +01:00
using Flowframes.Media ;
2021-02-01 16:23:35 +01:00
using Flowframes.Data ;
2020-11-23 16:51:05 +01:00
using Flowframes.Forms ;
using Flowframes.IO ;
2020-12-27 22:52:14 +01:00
using Flowframes.MiscUtils ;
2020-11-23 16:51:05 +01:00
using Flowframes.OS ;
using Flowframes.UI ;
using System ;
using System.Collections.Generic ;
2020-12-23 00:07:06 +01:00
using System.Diagnostics ;
2020-11-23 16:51:05 +01:00
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Text.RegularExpressions ;
2020-12-20 21:25:34 +01:00
using System.Threading.Tasks ;
2020-11-23 16:51:05 +01:00
using System.Windows.Forms ;
2021-02-12 00:44:37 +01:00
using I = Flowframes . Interpolate ;
2021-01-15 22:43:13 +01:00
using Padding = Flowframes . Data . Padding ;
2020-11-23 16:51:05 +01:00
namespace Flowframes.Main
{
class InterpolateUtils
{
public static PictureBox preview ;
public static BigPreviewForm bigPreviewForm ;
2021-02-14 22:23:16 +01:00
public static async Task CopyLastFrame ( int lastFrameNum )
2021-01-15 22:43:13 +01:00
{
2021-03-01 22:38:38 +01:00
if ( I . canceled ) return ;
2021-01-15 22:43:13 +01:00
try
{
lastFrameNum - - ; // We have to do this as extracted frames start at 0, not 1
2021-02-12 00:44:37 +01:00
bool frameFolderInput = IOUtils . IsPathDirectory ( I . current . inPath ) ;
string targetPath = Path . Combine ( I . current . framesFolder , lastFrameNum . ToString ( ) . PadLeft ( Padding . inputFrames , '0' ) + ".png" ) ;
2021-01-15 22:43:13 +01:00
if ( File . Exists ( targetPath ) ) return ;
2021-02-12 00:44:37 +01:00
Size res = IOUtils . GetImage ( IOUtils . GetFilesSorted ( I . current . framesFolder , false ) . First ( ) ) . Size ;
2021-01-15 22:43:13 +01:00
if ( frameFolderInput )
{
2021-02-12 00:44:37 +01:00
string lastFramePath = IOUtils . GetFilesSorted ( I . current . inPath , false ) . Last ( ) ;
2021-02-01 16:23:35 +01:00
await FfmpegExtract . ExtractLastFrame ( lastFramePath , targetPath , res ) ;
2021-01-15 22:43:13 +01:00
}
else
{
2021-02-12 00:44:37 +01:00
await FfmpegExtract . ExtractLastFrame ( I . current . inPath , targetPath , res ) ;
2021-01-15 22:43:13 +01:00
}
}
catch ( Exception e )
{
Logger . Log ( "CopyLastFrame Error: " + e . Message ) ;
}
}
2021-02-14 22:23:16 +01:00
public static string GetOutExt ( bool withDot = false )
2020-12-10 16:37:33 +01:00
{
2020-12-20 21:25:34 +01:00
string dotStr = withDot ? "." : "" ;
2021-01-16 00:19:23 +01:00
if ( Config . GetBool ( "jpegInterp" ) )
2020-12-20 21:25:34 +01:00
return dotStr + "jpg" ;
return dotStr + "png" ;
}
2021-02-11 09:05:10 +01:00
public static int lastFrame ;
2020-12-20 21:25:34 +01:00
public static int targetFrames ;
2021-01-18 15:32:45 +01:00
public static string currentOutdir ;
2021-02-01 18:05:50 +01:00
public static float currentFactor ;
2021-01-18 15:32:45 +01:00
public static bool progressPaused = false ;
public static bool progCheckRunning = false ;
2021-02-11 09:05:10 +01:00
2020-12-20 21:25:34 +01:00
public static async void GetProgressByFrameAmount ( string outdir , int target )
{
2021-01-18 15:32:45 +01:00
progCheckRunning = true ;
targetFrames = target ;
currentOutdir = outdir ;
Logger . Log ( $"Starting GetProgressByFrameAmount() loop for outdir '{currentOutdir}', target is {target} frames" , true ) ;
2020-12-20 21:25:34 +01:00
bool firstProgUpd = true ;
Program . mainForm . SetProgress ( 0 ) ;
2021-02-11 11:36:12 +01:00
lastFrame = 0 ;
2021-02-23 14:05:58 +01:00
peakFpsOut = 0f ;
2020-12-20 21:25:34 +01:00
while ( Program . busy )
{
2021-01-22 02:07:03 +01:00
if ( ! progressPaused & & AiProcess . processTime . IsRunning & & Directory . Exists ( currentOutdir ) )
2020-12-20 21:25:34 +01:00
{
if ( firstProgUpd & & Program . mainForm . IsInFocus ( ) )
Program . mainForm . SetTab ( "preview" ) ;
2021-02-11 21:18:00 +01:00
2020-12-20 21:25:34 +01:00
firstProgUpd = false ;
2021-02-11 12:58:07 +01:00
string lastFramePath = currentOutdir + "\\" + lastFrame . ToString ( "00000000" ) + $".{GetOutExt()}" ;
2021-02-11 21:18:00 +01:00
2021-02-11 09:05:10 +01:00
if ( lastFrame > 1 )
2021-02-11 12:58:07 +01:00
UpdateInterpProgress ( lastFrame , targetFrames , lastFramePath ) ;
2021-02-11 21:18:00 +01:00
2021-02-12 13:01:48 +01:00
await Task . Delay ( ( target < 1000 ) ? 100 : 200 ) ; // Update 10x/sec if interpolating <1k frames, otherwise 5x/sec
2021-02-11 21:18:00 +01:00
2021-02-11 09:05:10 +01:00
if ( lastFrame > = targetFrames )
2021-01-06 21:44:09 +01:00
break ;
2020-12-20 21:25:34 +01:00
}
2021-02-12 13:04:34 +01:00
else
{
await Task . Delay ( 100 ) ;
}
2020-12-20 21:25:34 +01:00
}
2021-02-23 14:05:58 +01:00
2021-01-18 15:32:45 +01:00
progCheckRunning = false ;
2021-02-23 14:05:58 +01:00
2021-02-12 00:44:37 +01:00
if ( I . canceled )
2021-01-22 01:43:47 +01:00
Program . mainForm . SetProgress ( 0 ) ;
2020-12-10 16:37:33 +01:00
}
2020-11-23 16:51:05 +01:00
2021-02-11 09:05:10 +01:00
public static void UpdateLastFrameFromInterpOutput ( string output )
{
2021-02-12 00:44:37 +01:00
try
{
string ncnnStr = I . current . ai . aiName . Contains ( "NCNN" ) ? " done" : "" ;
Regex frameRegex = new Regex ( $@"(?<=.)\d*(?=.{GetOutExt()}{ncnnStr})" ) ;
if ( ! frameRegex . IsMatch ( output ) ) return ;
lastFrame = Math . Max ( int . Parse ( frameRegex . Match ( output ) . Value ) , lastFrame ) ;
}
2021-02-12 01:09:48 +01:00
catch
{
Logger . Log ( $"UpdateLastFrameFromInterpOutput: Failed to get progress from '{output}' even though Regex matched!" ) ;
}
2021-02-11 09:05:10 +01:00
}
2021-02-01 23:18:13 +01:00
public static int interpolatedInputFramesCount ;
2021-02-23 14:05:58 +01:00
public static float peakFpsOut ;
2021-02-01 23:18:13 +01:00
2021-03-02 16:49:23 +01:00
public static int previewUpdateRateMs = 200 ;
2021-02-27 16:24:02 +01:00
2020-11-23 16:51:05 +01:00
public static void UpdateInterpProgress ( int frames , int target , string latestFramePath = "" )
{
2021-02-12 00:44:37 +01:00
if ( I . canceled ) return ;
interpolatedInputFramesCount = ( ( frames / I . current . interpFactor ) . RoundToInt ( ) - 1 ) ;
2021-01-30 01:37:36 +01:00
ResumeUtils . Save ( ) ;
2020-12-20 21:25:34 +01:00
frames = frames . Clamp ( 0 , target ) ;
2020-11-23 16:51:05 +01:00
int percent = ( int ) Math . Round ( ( ( float ) frames / target ) * 100f ) ;
Program . mainForm . SetProgress ( percent ) ;
2020-11-25 14:04:31 +01:00
float generousTime = ( ( AiProcess . processTime . ElapsedMilliseconds - AiProcess . lastStartupTimeMs ) / 1000f ) ;
2020-11-23 16:51:05 +01:00
float fps = ( float ) frames / generousTime ;
2020-12-20 21:25:34 +01:00
string fpsIn = ( fps / currentFactor ) . ToString ( "0.00" ) ;
2020-11-23 16:51:05 +01:00
string fpsOut = fps . ToString ( "0.00" ) ;
2021-02-23 14:05:58 +01:00
if ( fps > peakFpsOut )
peakFpsOut = fps ;
2020-11-23 16:51:05 +01:00
float secondsPerFrame = generousTime / ( float ) frames ;
int framesLeft = target - frames ;
float eta = framesLeft * secondsPerFrame ;
2020-12-20 21:25:34 +01:00
string etaStr = FormatUtils . Time ( new TimeSpan ( 0 , 0 , eta . RoundToInt ( ) ) , false ) ;
2020-11-23 16:51:05 +01:00
2021-02-11 12:44:42 +01:00
bool replaceLine = Regex . Split ( Logger . textbox . Text , "\r\n|\r|\n" ) . Last ( ) . Contains ( "Average Speed: " ) ;
2020-11-30 02:14:04 +01:00
2021-02-11 12:44:42 +01:00
string logStr = $"Interpolated {frames}/{target} Frames ({percent}%) - Average Speed: {fpsIn} FPS In / {fpsOut} FPS Out - " ;
2020-11-30 02:14:04 +01:00
logStr + = $"Time: {FormatUtils.Time(AiProcess.processTime.Elapsed)} - ETA: {etaStr}" ;
if ( AutoEncode . busy ) logStr + = " - Encoding..." ;
Logger . Log ( logStr , false , replaceLine ) ;
2020-11-23 16:51:05 +01:00
try
{
2020-12-20 21:25:34 +01:00
if ( ! string . IsNullOrWhiteSpace ( latestFramePath ) & & frames > currentFactor )
2020-11-23 16:51:05 +01:00
{
if ( bigPreviewForm = = null & & ! preview . Visible /* ||Program.mainForm.WindowState != FormWindowState.Minimized */ /* || !Program.mainForm.IsInFocus()*/ ) return ; // Skip if the preview is not visible or the form is not in focus
2021-02-28 13:46:50 +01:00
if ( timeSinceLastPreviewUpdate . IsRunning & & timeSinceLastPreviewUpdate . ElapsedMilliseconds < previewUpdateRateMs ) return ;
2020-11-23 16:51:05 +01:00
Image img = IOUtils . GetImage ( latestFramePath ) ;
2020-11-27 14:35:32 +01:00
SetPreviewImg ( img ) ;
2020-11-23 16:51:05 +01:00
}
}
2021-02-28 13:46:50 +01:00
catch ( Exception e )
{
Logger . Log ( "Error updating preview: " + e . Message , true ) ;
}
2020-11-23 16:51:05 +01:00
}
2021-02-11 11:36:12 +01:00
public static async Task DeleteInterpolatedInputFrames ( )
2021-02-01 23:18:13 +01:00
{
2021-02-02 16:07:36 +01:00
interpolatedInputFramesCount = 0 ;
2021-02-12 00:44:37 +01:00
string [ ] inputFrames = IOUtils . GetFilesSorted ( I . current . framesFolder ) ;
2021-02-01 23:18:13 +01:00
for ( int i = 0 ; i < inputFrames . Length ; i + + )
{
2021-02-02 21:48:18 +01:00
while ( Program . busy & & ( i + 10 ) > interpolatedInputFramesCount ) await Task . Delay ( 1000 ) ;
2021-02-01 23:18:13 +01:00
if ( ! Program . busy ) break ;
2021-02-14 22:23:16 +01:00
if ( i ! = 0 & & i ! = inputFrames . Length - 1 )
2021-02-01 23:18:13 +01:00
IOUtils . OverwriteFileWithText ( inputFrames [ i ] ) ;
if ( i % 10 = = 0 ) await Task . Delay ( 10 ) ;
}
}
2021-02-27 16:24:02 +01:00
public static Stopwatch timeSinceLastPreviewUpdate = new Stopwatch ( ) ;
2021-02-11 11:36:12 +01:00
public static void SetPreviewImg ( Image img )
2020-11-27 14:35:32 +01:00
{
if ( img = = null )
return ;
2021-02-04 21:18:36 +01:00
2021-02-27 16:24:02 +01:00
timeSinceLastPreviewUpdate . Restart ( ) ;
2020-11-27 14:35:32 +01:00
preview . Image = img ;
2021-02-04 21:18:36 +01:00
2020-11-27 14:35:32 +01:00
if ( bigPreviewForm ! = null )
bigPreviewForm . SetImage ( img ) ;
}
2021-02-14 22:23:16 +01:00
public static Dictionary < PseudoUniqueFile , int > frameCountCache = new Dictionary < PseudoUniqueFile , int > ( ) ;
public static async Task < int > GetInputFrameCountAsync ( string path )
2020-12-07 00:41:07 +01:00
{
2021-02-14 22:23:16 +01:00
long filesize = IOUtils . GetFilesize ( path ) ;
PseudoUniqueFile hash = new PseudoUniqueFile ( path , filesize ) ;
2021-02-01 21:50:05 +01:00
2021-02-14 22:23:16 +01:00
if ( filesize > 0 & & FrameCountCacheContains ( hash ) )
2020-12-27 22:52:14 +01:00
{
2021-02-14 22:23:16 +01:00
Logger . Log ( $"FrameCountCache contains this hash, using cached frame count." , true ) ;
return GetFrameCountFromCache ( hash ) ;
2020-12-27 22:52:14 +01:00
}
else
{
2021-02-14 22:23:16 +01:00
Logger . Log ( $"Hash not cached, reading frame count." , true ) ;
2020-12-27 22:52:14 +01:00
}
2021-02-14 22:23:16 +01:00
int frameCount ;
2021-02-08 10:21:26 +01:00
2020-12-07 00:41:07 +01:00
if ( IOUtils . IsPathDirectory ( path ) )
2020-12-27 22:52:14 +01:00
frameCount = IOUtils . GetAmountOfFiles ( path , false ) ;
2020-12-07 00:41:07 +01:00
else
2021-02-02 12:56:48 +01:00
frameCount = await FfmpegCommands . GetFrameCountAsync ( path ) ;
2020-12-27 22:52:14 +01:00
2021-02-14 22:23:16 +01:00
Logger . Log ( $"Adding hash with frame count {frameCount} to cache." , true ) ;
frameCountCache . Add ( hash , frameCount ) ;
2021-02-01 21:50:05 +01:00
2020-12-27 22:52:14 +01:00
return frameCount ;
2020-12-07 00:41:07 +01:00
}
2021-02-14 22:23:16 +01:00
private static bool FrameCountCacheContains ( PseudoUniqueFile hash )
{
foreach ( KeyValuePair < PseudoUniqueFile , int > entry in frameCountCache )
if ( entry . Key . path = = hash . path & & entry . Key . filesize = = hash . filesize )
return true ;
return false ;
}
private static int GetFrameCountFromCache ( PseudoUniqueFile hash )
{
foreach ( KeyValuePair < PseudoUniqueFile , int > entry in frameCountCache )
if ( entry . Key . path = = hash . path & & entry . Key . filesize = = hash . filesize )
return entry . Value ;
return 0 ;
}
2020-11-23 16:51:05 +01:00
public static int GetProgressWaitTime ( int numFrames )
{
2021-01-07 11:02:43 +01:00
float hddMultiplier = ! Program . lastInputPathIsSsd ? 2f : 1f ;
2020-11-23 16:51:05 +01:00
int waitMs = 200 ;
if ( numFrames > 100 )
waitMs = 500 ;
if ( numFrames > 1000 )
waitMs = 1000 ;
if ( numFrames > 2500 )
waitMs = 1500 ;
if ( numFrames > 5000 )
waitMs = 2500 ;
return ( waitMs * hddMultiplier ) . RoundToInt ( ) ;
}
2021-02-14 22:23:16 +01:00
public static string GetTempFolderLoc ( string inPath , string outPath )
2020-11-23 16:51:05 +01:00
{
string basePath = inPath . GetParentDir ( ) ;
2021-01-07 11:02:43 +01:00
2021-02-14 22:23:16 +01:00
if ( Config . GetInt ( "tempFolderLoc" ) = = 1 )
2020-11-23 16:51:05 +01:00
basePath = outPath . GetParentDir ( ) ;
2021-01-07 11:02:43 +01:00
2020-11-23 16:51:05 +01:00
if ( Config . GetInt ( "tempFolderLoc" ) = = 2 )
basePath = outPath ;
2021-01-07 11:02:43 +01:00
2020-11-23 16:51:05 +01:00
if ( Config . GetInt ( "tempFolderLoc" ) = = 3 )
2021-02-18 14:30:56 +01:00
basePath = Paths . GetExeDir ( ) ;
2021-01-07 11:02:43 +01:00
2020-11-23 16:51:05 +01:00
if ( Config . GetInt ( "tempFolderLoc" ) = = 4 )
{
string custPath = Config . Get ( "tempDirCustom" ) ;
2021-02-14 22:23:16 +01:00
if ( IOUtils . IsDirValid ( custPath ) )
2020-11-23 16:51:05 +01:00
basePath = custPath ;
}
2020-12-04 16:53:39 +01:00
return Path . Combine ( basePath , Path . GetFileNameWithoutExtension ( inPath ) . StripBadChars ( ) . Remove ( " " ) . Trunc ( 30 , false ) + "-temp" ) ;
2020-11-23 16:51:05 +01:00
}
2021-02-01 18:05:50 +01:00
public static bool InputIsValid ( string inDir , string outDir , float fpsOut , float factor , Interpolate . OutMode outMode )
2020-11-23 16:51:05 +01:00
{
2020-12-04 16:53:39 +01:00
bool passes = true ;
2020-11-23 16:51:05 +01:00
bool isFile = ! IOUtils . IsPathDirectory ( inDir ) ;
2020-12-06 18:49:53 +01:00
if ( ( passes & & isFile & & ! IOUtils . IsFileValid ( inDir ) ) | | ( ! isFile & & ! IOUtils . IsDirValid ( inDir ) ) )
2020-11-23 16:51:05 +01:00
{
ShowMessage ( "Input path is not valid!" ) ;
passes = false ;
}
2020-12-06 18:49:53 +01:00
if ( passes & & ! IOUtils . IsDirValid ( outDir ) )
2020-11-23 16:51:05 +01:00
{
ShowMessage ( "Output path is not valid!" ) ;
passes = false ;
}
2021-02-01 18:05:50 +01:00
if ( passes & & /*factor != 2 && factor != 4 && factor != 8*/ factor > 16 )
2020-11-23 16:51:05 +01:00
{
ShowMessage ( "Interpolation factor is not valid!" ) ;
passes = false ;
}
2021-02-20 00:18:00 +01:00
if ( passes & & outMode = = I . OutMode . VidGif & & fpsOut > 50 & & ! ( Config . GetFloat ( "maxFps" ) ! = 0 & & Config . GetFloat ( "maxFps" ) < = 50 ) )
2021-01-07 12:15:13 +01:00
{
2021-02-11 21:47:06 +01:00
ShowMessage ( "Invalid output frame rate!\nGIF does not properly support frame rates above 50 FPS.\nPlease use MP4, WEBM or another video format." ) ;
2021-01-07 12:15:13 +01:00
passes = false ;
}
2021-02-04 22:50:07 +01:00
if ( passes & & fpsOut < 1 | | fpsOut > 1000 )
2020-11-23 16:51:05 +01:00
{
2021-02-04 22:50:07 +01:00
ShowMessage ( "Invalid output frame rate - Must be 1-1000." ) ;
2020-11-23 16:51:05 +01:00
passes = false ;
}
if ( ! passes )
2021-02-12 00:44:37 +01:00
I . Cancel ( "Invalid settings detected." , true ) ;
2020-11-23 16:51:05 +01:00
return passes ;
}
2021-02-14 22:23:16 +01:00
public static void PathAsciiCheck ( string path , string pathTitle )
{
2021-02-01 22:06:50 +01:00
if ( IOUtils . HasBadChars ( path ) | | OSUtils . HasNonAsciiChars ( path ) )
ShowMessage ( $"Warning: Your {pathTitle} includes special characters. This might cause problems." ) ;
2020-11-23 16:51:05 +01:00
}
2021-02-14 22:23:16 +01:00
public static bool CheckAiAvailable ( AI ai )
2020-11-23 16:51:05 +01:00
{
2020-11-25 14:04:31 +01:00
if ( ! PkgUtils . IsAiAvailable ( ai ) )
2020-11-23 16:51:05 +01:00
{
2021-02-18 14:30:56 +01:00
ShowMessage ( "The selected AI is not installed!" , "Error" ) ;
2021-02-12 00:44:37 +01:00
I . Cancel ( "Selected AI not available." , true ) ;
2020-11-23 16:51:05 +01:00
return false ;
}
2021-02-24 15:08:18 +01:00
if ( I . current . ai . aiName . ToUpper ( ) . Contains ( "CUDA" ) & & NvApi . gpuList . Count < 1 )
{
ShowMessage ( "An Nvidia GPU is required for CUDA implementations!\n\nTry an NCNN implementation instead." , "Error" ) ;
I . Cancel ( "No CUDA-capable graphics card available." , true ) ;
return false ;
}
2020-11-23 16:51:05 +01:00
return true ;
}
2021-02-14 22:23:16 +01:00
public static bool CheckDeleteOldTempFolder ( )
2020-11-23 16:51:05 +01:00
{
2021-02-12 00:44:37 +01:00
if ( ! IOUtils . TryDeleteIfExists ( I . current . tempFolder ) )
2020-11-23 16:51:05 +01:00
{
ShowMessage ( "Failed to remove an existing temp folder of this video!\nMake sure you didn't open any frames in an editor." , "Error" ) ;
2021-02-12 00:44:37 +01:00
I . Cancel ( ) ;
2020-11-23 16:51:05 +01:00
return false ;
}
return true ;
}
2021-02-14 22:23:16 +01:00
public static bool CheckPathValid ( string path )
2020-11-23 16:51:05 +01:00
{
if ( IOUtils . IsPathDirectory ( path ) )
{
if ( ! IOUtils . IsDirValid ( path ) )
{
ShowMessage ( "Input directory is not valid." ) ;
2021-02-12 00:44:37 +01:00
I . Cancel ( ) ;
2020-11-23 16:51:05 +01:00
return false ;
}
}
else
{
if ( ! IsVideoValid ( path ) )
{
ShowMessage ( "Input video file is not valid." ) ;
return false ;
}
}
return true ;
}
2021-02-21 21:18:31 +01:00
public static async Task < bool > CheckEncoderValid ( )
{
string enc = FFmpegUtils . GetEnc ( FFmpegUtils . GetCodec ( I . current . outMode ) ) ;
if ( ! enc . ToLower ( ) . Contains ( "nvenc" ) )
return true ;
if ( ! ( await FfmpegCommands . IsEncoderCompatible ( enc ) ) )
{
ShowMessage ( "NVENC encoding is not available on your hardware!\nPlease use a different encoder." , "Error" ) ;
I . Cancel ( ) ;
return false ;
}
return true ;
}
2020-11-23 16:51:05 +01:00
public static bool IsVideoValid ( string videoPath )
{
if ( videoPath = = null | | ! IOUtils . IsFileValid ( videoPath ) )
return false ;
2020-12-13 23:44:23 +01:00
return true ;
2020-11-23 16:51:05 +01:00
}
public static void ShowMessage ( string msg , string title = "Message" )
{
if ( ! BatchProcessing . busy )
MessageBox . Show ( msg , title ) ;
Logger . Log ( "Message: " + msg , true ) ;
}
2020-12-15 14:46:33 +01:00
2021-02-14 22:23:16 +01:00
public static async Task < Size > GetOutputResolution ( string inputPath , bool print , bool returnZeroIfUnchanged = false )
2020-12-15 14:46:33 +01:00
{
2021-01-15 15:07:40 +01:00
Size resolution = await IOUtils . GetVideoOrFramesRes ( inputPath ) ;
2021-01-27 11:41:05 +01:00
return GetOutputResolution ( resolution , print , returnZeroIfUnchanged ) ;
2020-12-22 23:45:07 +01:00
}
2021-01-27 11:41:05 +01:00
public static Size GetOutputResolution ( Size inputRes , bool print = false , bool returnZeroIfUnchanged = false )
2020-12-22 23:45:07 +01:00
{
2020-12-15 14:46:33 +01:00
int maxHeight = RoundDiv2 ( Config . GetInt ( "maxVidHeight" ) ) ;
2020-12-22 23:45:07 +01:00
if ( inputRes . Height > maxHeight )
2020-12-15 14:46:33 +01:00
{
2020-12-22 23:45:07 +01:00
float factor = ( float ) maxHeight / inputRes . Height ;
Logger . Log ( $"Un-rounded downscaled size: {(inputRes.Width * factor).ToString(" 0.00 ")}x{Config.GetInt(" maxVidHeight ")}" , true ) ;
int width = RoundDiv2 ( ( inputRes . Width * factor ) . RoundToInt ( ) ) ;
if ( print )
2020-12-21 15:03:31 +01:00
Logger . Log ( $"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}." ) ;
2020-12-15 14:46:33 +01:00
return new Size ( width , maxHeight ) ;
}
else
{
2021-01-27 11:41:05 +01:00
//return new Size(RoundDiv2(inputRes.Width), RoundDiv2(inputRes.Height));
if ( returnZeroIfUnchanged )
return new Size ( ) ;
else
return inputRes ;
2020-12-15 14:46:33 +01:00
}
}
2021-01-17 20:05:39 +01:00
public static int RoundDiv2 ( int n ) // Round to a number that's divisible by 2 (for h264 etc)
2020-12-15 14:46:33 +01:00
{
int a = ( n / 2 ) * 2 ; // Smaller multiple
int b = a + 2 ; // Larger multiple
return ( n - a > b - n ) ? b : a ; // Return of closest of two
}
2020-12-23 00:07:06 +01:00
2021-02-14 22:23:16 +01:00
public static bool CanUseAutoEnc ( bool stepByStep , InterpSettings current )
2021-01-05 17:23:37 +01:00
{
2021-01-06 17:41:18 +01:00
AutoEncode . UpdateChunkAndBufferSizes ( ) ;
2021-01-05 17:23:37 +01:00
2021-01-18 15:32:45 +01:00
if ( current . alpha )
{
Logger . Log ( $"Not Using AutoEnc: Alpha mode is enabled." , true ) ;
return false ;
}
if ( ! current . outMode . ToString ( ) . ToLower ( ) . Contains ( "vid" ) | | current . outMode . ToString ( ) . ToLower ( ) . Contains ( "gif" ) )
2021-01-05 17:23:37 +01:00
{
Logger . Log ( $"Not Using AutoEnc: Out Mode is not video ({current.outMode.ToString()})" , true ) ;
return false ;
}
2021-02-14 22:23:16 +01:00
if ( stepByStep & & ! Config . GetBool ( "sbsAllowAutoEnc" ) )
2021-01-05 17:23:37 +01:00
{
Logger . Log ( $"Not Using AutoEnc: Using step-by-step mode, but 'sbsAllowAutoEnc' is false." , true ) ;
return false ;
}
if ( ! stepByStep & & Config . GetInt ( "autoEncMode" ) = = 0 )
{
Logger . Log ( $"Not Using AutoEnc: 'autoEncMode' is 0." , true ) ;
return false ;
}
int inFrames = IOUtils . GetAmountOfFiles ( current . framesFolder , false ) ;
if ( inFrames * current . interpFactor < ( AutoEncode . chunkSize + AutoEncode . safetyBufferFrames ) * 1.2f )
{
2021-01-06 17:41:18 +01:00
Logger . Log ( $"Not Using AutoEnc: Input frames ({inFrames}) * factor ({current.interpFactor}) is smaller than (chunkSize ({AutoEncode.chunkSize}) + safetyBufferFrames ({AutoEncode.safetyBufferFrames}) * 1.2f)" , true ) ;
2021-01-05 17:23:37 +01:00
return false ;
}
return true ;
}
2021-02-14 22:23:16 +01:00
public static async Task < bool > UseUHD ( )
2021-01-05 17:23:37 +01:00
{
2021-02-12 00:44:37 +01:00
return ( await GetOutputResolution ( I . current . inPath , false ) ) . Height > = Config . GetInt ( "uhdThresh" ) ;
2021-01-05 17:23:37 +01:00
}
2021-02-14 22:23:16 +01:00
public static void FixConsecutiveSceneFrames ( string sceneFramesPath , string sourceFramesPath )
2020-12-23 00:07:06 +01:00
{
2020-12-23 12:42:06 +01:00
if ( ! Directory . Exists ( sceneFramesPath ) | | IOUtils . GetAmountOfFiles ( sceneFramesPath , false ) < 1 )
return ;
2020-12-23 00:07:06 +01:00
List < string > sceneFrames = IOUtils . GetFilesSorted ( sceneFramesPath ) . Select ( x = > Path . GetFileNameWithoutExtension ( x ) ) . ToList ( ) ;
List < string > sourceFrames = IOUtils . GetFilesSorted ( sourceFramesPath ) . Select ( x = > Path . GetFileNameWithoutExtension ( x ) ) . ToList ( ) ;
List < string > sceneFramesToDelete = new List < string > ( ) ;
2021-02-14 22:23:16 +01:00
foreach ( string scnFrame in sceneFrames )
2020-12-23 00:07:06 +01:00
{
if ( sceneFramesToDelete . Contains ( scnFrame ) )
continue ;
int sourceIndexForScnFrame = sourceFrames . IndexOf ( scnFrame ) ; // Get source index of scene frame
2020-12-23 16:13:04 +01:00
if ( ( sourceIndexForScnFrame + 1 ) = = sourceFrames . Count )
continue ;
2020-12-23 00:07:06 +01:00
string followingFrame = sourceFrames [ sourceIndexForScnFrame + 1 ] ; // Get filename/timestamp of the next source frame
if ( sceneFrames . Contains ( followingFrame ) ) // If next source frame is in scene folder, add to deletion list
sceneFramesToDelete . Add ( followingFrame ) ;
}
foreach ( string frame in sceneFramesToDelete )
IOUtils . TryDeleteIfExists ( Path . Combine ( sceneFramesPath , frame + ".png" ) ) ;
}
2020-11-23 16:51:05 +01:00
}
}