CalculateSize() public method

Calculates FrameDouble, CropSource, CropAfter and OutputWidth values.
public CalculateSize ( ) : void
return void
        /// <summary>
        /// Prepares the files of an existing job that we resume.
        /// </summary>
        /// <returns>Whether job still needs to execute.</returns>
        //private bool PrepareResumeJob(MediaEncoderSettings settings) {
        //    AvisynthTools.EditStartPosition(settings.ScriptFile, 0);
        //    // At least one segment has been processed. Check if the entire file has been processed.
        //    ProcessStartOptions Options = new ProcessStartOptions(settings.JobIndex, "Resuming...", false).TrackProcess(settings);
        //    Task<long> TaskCount = Task.Run(() => AvisynthTools.GetFrameCount(settings.ScriptFile, Options));

        //    int Segment = 0;
        //    List<Task<long>> TaskList = new List<Task<long>>();
        //    while (File.Exists(PathManager.GetOutputFile(settings.JobIndex, ++Segment, settings.VideoCodec)) && settings.CompletionStatus != CompletionStatus.Cancelled) {
        //        string SegmentFile = PathManager.GetOutputFile(settings.JobIndex, Segment, settings.VideoCodec);
        //        // Discard segments of less than 10kb.
        //        if (new FileInfo(SegmentFile).Length > 10000) {
        //            int SegmentLocal = Segment;
        //            TaskList.Add(Task.Run(() => AvisynthTools.GetFrameCount(PathManager.GetOutputFile(settings.JobIndex, SegmentLocal, settings.VideoCodec), null)));
        //        } else {
        //            // There shouldn't be any resumed job following a segment that is being deleted.
        //            File.Delete(SegmentFile);
        //            break;
        //        }
        //    }

        //    long OutputFrames = 0;
        //    Task.WaitAll(TaskList.ToArray());
        //    foreach (Task<long> item in TaskList) {
        //        OutputFrames += item.Result;
        //    }

        //    TaskCount.Wait();
        //    if (settings.CompletionStatus == CompletionStatus.Cancelled)
        //        return false;

        //    long ScriptFrames = TaskCount.Result;
        //    if (OutputFrames >= ScriptFrames) {
        //        // Job completed.
        //        //EncodingCompletedEventArgs EncodeResult = FinalizeEncoding(settings, null);
        //        //if (EncodeResult != null)
        //        //    EncodingCompleted(this, EncodeResult);
        //        //else {
        //        //    PathManager.DeleteJobFiles(settings.JobIndex);
        //        //}
        //        return false;
        //    } else {
        //        // Resume with new segment.
        //        AvisynthTools.EditStartPosition(settings.ScriptFile, OutputFrames);
        //        settings.ResumeSegment = Segment;
        //        settings.ResumePos = OutputFrames;
        //        File.Delete(settings.OutputFile);
        //        return true;
        //    }
        //}

        private async Task GetMediaInfo(string previewFile, MediaEncoderSettings settings) {
            FFmpegProcess FInfo = await Task.Run(() => MediaInfo.GetFileInfo(previewFile));
            FFmpegVideoStreamInfo VInfo = FInfo.VideoStream;
            FFmpegAudioStreamInfo AInfo = settings.ConvertToAvi ? await Task.Run(() => MediaInfo.GetFileInfo(settings.FilePath).AudioStream) : FInfo.AudioStream;

            settings.SourceWidth = FInfo.VideoStream.Width;
            settings.SourceHeight = FInfo.VideoStream.Height;
            if (settings.SourceHeight > 768)
                settings.OutputHeight = settings.SourceHeight.Value;
            settings.SourceAspectRatio = (float)(VInfo?.PixelAspectRatio ?? 1);
            // Fix last track of VCDs that is widescreen.
            if (settings.SourceHeight == 288 && settings.SourceWidth == 352 && settings.SourceAspectRatio == 1.485f)
                settings.SourceAspectRatio = 1.092f;
            settings.SourceFrameRate = VInfo?.FrameRate;

            settings.SourceAudioFormat = AInfo?.Format;
            settings.SourceVideoFormat = VInfo?.Format;
            bool IsTvRange = VInfo?.ColorRange != "pc";
            if (!string.IsNullOrEmpty(VInfo?.ColorMatrix)) {
                settings.SourceColorMatrix = VInfo.ColorMatrix.EndsWith("601") ? (IsTvRange ? ColorMatrix.Rec601 : ColorMatrix.Pc601) : (IsTvRange ? ColorMatrix.Rec709 : ColorMatrix.Pc709);
            } else
                settings.SourceColorMatrix = VInfo?.Height < 600 ? (IsTvRange ? ColorMatrix.Rec601 : ColorMatrix.Pc601) : (IsTvRange ? ColorMatrix.Rec709 : ColorMatrix.Pc709);
            settings.SourceChromaPlacement = string.Compare(VInfo?.Format, "mpeg1video", true) == 0 ? ChromaPlacement.MPEG1 : ChromaPlacement.MPEG2;
            settings.DegrainPrefilter = VInfo?.Height < 600 ? DegrainPrefilters.SD : DegrainPrefilters.HD;

            settings.SourceVideoBitrate = (int)(new FileInfo(previewFile).Length / FInfo.FileDuration.TotalSeconds / 1024 * 8);
            settings.SourceAudioBitrate = AInfo?.Bitrate;
            if (!settings.HasAudioOptions)
                settings.AudioQuality = AInfo?.Bitrate > 0 ? AInfo.Bitrate : 256;
            if (settings.AudioQuality > 384)
                settings.AudioQuality = 384;
            settings.SourceBitDepth = 8; // VInfo.BitDepth;
            //settings.DenoiseD = 2;
            //settings.DenoiseA = settings.SourceHeight < 720 ? 2 : 1;
            settings.Position = FInfo.FileDuration.TotalSeconds / 2;
            settings.VideoAction = settings.SourceHeight >= 1080 ? VideoAction.x264 : VideoAction.x265;
            settings.EncodeQuality = settings.SourceHeight >= 1080 ? 23 : 22;
            settings.EncodePreset = settings.SourceHeight >= 1080 ? EncodePresets.veryslow : EncodePresets.medium;
            // Use Cache to open file when file is over 500MB
            settings.CalculateSize();
        }
        public static AviSynthScriptBuilder GenerateVideoScript(MediaEncoderSettings settings, string inputFile, bool preview, bool multiThreaded)
        {
            // int CPU = multiThreaded ? Environment.ProcessorCount : 1;
            int CPU = multiThreaded ? settings.Threads : 1;

            if (CPU <= 1)
            {
                multiThreaded = false;
            }
            bool RunMultiProcesses = false;

            if (settings.Deshaker && multiThreaded)
            {
                RunMultiProcesses = true;  // Run through MP_Pipeline
                multiThreaded     = false; // Deshaker doesn't work with MT
                CPU = 1;
            }
            //if (settings.Threads > 0) {
            //    multiThreaded = false;
            //    CPU = 1;
            //}

            settings.CalculateSize();

            // Calculate encoding and final frame rates.
            double ChangeSpeedValue = (settings.ChangeSpeed && settings.CanAlterAudio) ? (double)settings.ChangeSpeedValue / 100 : 1;
            double FrameRateBefore  = settings.SourceFrameRate.Value * ChangeSpeedValue;

            // Generate video script.
            AviSynthScriptBuilder Script = new AviSynthScriptBuilder();
            bool IsYV24 = false;

            Script.AppendLine(); // After clean-up, this adds a line after LoadPlugin commands.
            Script.AddPluginPath();
            if (multiThreaded)
            {
                Script.LoadPluginAvsi("AviSynthMT.avsi");
            }
            if (settings.ConvertToAvi || inputFile.ToLower().EndsWith(".avi"))
            {
                Script.OpenAvi(inputFile, !string.IsNullOrEmpty(settings.SourceAudioFormat));
            }
            else
            {
                Script.OpenDirect(inputFile, !string.IsNullOrEmpty(settings.SourceAudioFormat));
            }
            if (FrameRateBefore != settings.SourceFrameRate)
            {
                Script.AppendLine(CultureInfo.InvariantCulture, "AssumeFPS({0}, true)", FrameRateBefore);
            }
            if (settings.Trim && settings.CanAlterAudio)
            {
                Script.AppendLine("Trim({0}, {1})",
                                  (settings.TrimStart ?? 0) > 0 ? (int)(settings.TrimStart.Value * settings.SourceFrameRate.Value) : 0,
                                  (settings.TrimEnd ?? 0) > 0 && !preview ? (int)(settings.TrimEnd.Value * settings.SourceFrameRate.Value) : 0);
            }

            if (settings.Denoise)
            {
                //Script.LoadPluginDll("MvTools2.dll");
                //Script.LoadPluginDll("MaskTools2.dll");
                //Script.LoadPluginDll("FFT3DFilter.dll");
                //Script.LoadPluginDll("ModPlus.dll");
                //Script.LoadPluginDll("RgTools.dll");
                //Script.LoadPluginDll("DCTFilter.dll");
                //Script.LoadPluginAvsi("mClean.avsi");
                //Script.AppendLine("mClean(rn={0}{1})", 10, IsHD ? ", outbits=16" : "");
                Script.AppendLine(@"MCTemporalDenoise(settings=""{0}""{1})", "medium", settings.Deblock ? ", deblock=true" : "");
            }
            else if (settings.Deblock)
            {
                Script.LoadPluginDll("MaskTools2.dll");
                Script.LoadPluginDll("DCTFilter.dll");
                Script.LoadPluginDll("deblock.dll");
                Script.LoadPluginAvsi("Deblock_QED.avsi");
                Script.AppendLine("Deblock_QED()");
            }

            if (settings.CropSource.HasValue)
            {
                Script.AppendLine("Crop({0}, {1}, -{2}, -{3})", settings.CropSource.Left, settings.CropSource.Top, settings.CropSource.Right, settings.CropSource.Bottom);
            }

            // If possible, KNLMeans will output 16-bit frames before upscaling.
            bool IsHD            = (settings.Dering || settings.Deblock || settings.Degrain || settings.SourceColorMatrix != ColorMatrix.Rec709 || (settings.FrameDouble > 0 && (settings.SuperRes || settings.UpscaleMethod == UpscaleMethods.SuperXbr)));
            bool IsColorMatrixHD = IsHD;
            bool IsChromaFixed   = settings.SourceChromaPlacement == ChromaPlacement.MPEG2;

            if (IsHD)
            {
                //if (!settings.Denoise)
                Script.AppendLine("ConvertBits(16)");
                if (settings.SourceColorMatrix != ColorMatrix.Rec709)
                {
                    Script.AppendLine("[ColorMatrixShader]"); // Placeholder that will be replaced after generating the rest.
                }
            }

            if (settings.FixDoubleFrames)
            {
                Script.LoadPluginDll("FrameRateConverter.dll");
                Script.LoadPluginAvsi("FrameRateConverter.avsi");
                Script.LoadPluginDll("MaskTools2.dll");
                Script.LoadPluginDll("MvTools2.dll");
                Script.AppendLine("InterpolateDoubles(.1)");
            }

            if (settings.Dering)
            {
                Script.LoadPluginAvsi("HQDeringmod.avsi");
                Script.LoadPluginDll("MedianBlur2.dll");
                Script.LoadPluginDll("dfttest.dll");
                Script.LoadPluginDll("RgTools.dll");
                Script.LoadPluginDll("SmoothAdjust.dll");
                Script.AppendLine("HQDeringmod({0})", IsHD ? "lsb_in=true, lsb=true" : "");
            }

            if (settings.Degrain)
            {
                ApplyDegrain(Script, settings, ref IsHD, ref IsYV24);
            }
            if (settings.Deshaker)
            {
                ApplyDeshaker(Script, settings, ref IsHD, ref IsYV24, RunMultiProcesses);
            }

            if (settings.FrameDouble > 0)
            {
                Script.AppendLine(@"ConvertToYUV444({0})",
                                  !IsChromaFixed ? string.Format(@"ChromaInPlacement=""{0}""", settings.SourceChromaPlacement.ToString()) : "");
                IsYV24        = true;
                IsChromaFixed = true;
            }

            string FinalSize = string.Format("fWidth={0}, fHeight={1}",
                                             settings.OutputWidth + settings.CropAfter.Left + settings.CropAfter.Right,
                                             settings.OutputHeight + settings.CropAfter.Top + settings.CropAfter.Bottom);
            string FinalResize = FinalSize;

            if (settings.DownscaleMethod == DownscaleMethods.SSim)
            {
                FinalResize += string.Format(@", fKernel=""SSim"", fB={0}{1}",
                                             settings.SSimStrength / 100, settings.SSimSoft ? ", fC=1" : "");
            }
            else // DownscaleMethod == Bicubic
            {
                FinalResize += string.Format(@", fKernel=""Bicubic"", fB=0, fC=.75");
            }

            if (settings.FrameDouble > 0)
            {
                if (settings.UpscaleMethod == UpscaleMethods.NNedi3)
                {
                    bool IsLastDouble = false;
                    DitherPost(Script, ref IsHD, ref IsYV24, true);

                    Script.LoadPluginDll("nnedi3.dll");
                    Script.LoadPluginAvsi("edi_rpow2.avsi");
                    Script.LoadPluginAvsi("ResizeX.avsi");

                    for (int i = 0; i < settings.FrameDouble; i++)
                    {
                        IsLastDouble = i == settings.FrameDouble - 1;
                        string DoubleScript = string.Format("edi_rpow2(2, nns=4, {0}, Threads=2)",
                                                            IsLastDouble && settings.DownscaleMethod == DownscaleMethods.Bicubic ? @"cshift=""Bicubic"", a1=0, a2=.75, " + FinalSize : @"cshift=""Spline16Resize""");
                        if (settings.SuperRes)
                        {
                            Script.AppendLine(CultureInfo.InvariantCulture, @"SuperRes({0}, {1}, {2}, """"""{3}""""""{4}{5}{6})",
                                              settings.SuperRes3Passes ? (i == 0 && settings.FrameDouble > 1 ? 5 : 3) : 2,
                                              settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f, DoubleScript,
                                              i == 0 ? GetMatrixIn(settings) : "",
                                              IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim ? ", " + FinalResize : "",
                                              multiThreaded ? "" : ", Engines=1");
                        }
                        else
                        {
                            Script.AppendLine(DoubleScript);
                            if (IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim)
                            {
                                Script.AppendLine("ResizeShader({0}{1})",
                                                  FinalResize.Replace("fWidth=", "").Replace("fHeight=", "").Replace(" f", " "), // Use same string as FinalResize but remove 'f' parameter sufix.
                                                  GetMatrixIn(settings));
                            }
                        }
                    }
                }
                else     // UpscaleMethod == SuperXBR
                {
                    if (settings.SuperRes)
                    {
                        Script.AppendLine(CultureInfo.InvariantCulture, @"SuperResXBR({0}, {1}, {2}{3}, XbrStr={4}, XbrSharp={5}{6}, {7}, FormatOut=""YV12""{8})",
                                          settings.SuperRes3Passes ? (settings.IncreaseFrameRate ? 5 : 3) : 2,
                                          settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f,
                                          settings.FrameDouble > 1 ? ", Factor=" + (1 << settings.FrameDouble).ToString() : "",
                                          settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                          GetMatrixIn(settings),
                                          FinalResize,
                                          multiThreaded ? "" : ", Engines=1");
                    }
                    else
                    {
                        Script.AppendLine(@"SuperXBR(Str={0}, Sharp={1}{2}{3}, {4}, FormatOut=""YV12""{5})",
                                          settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                          settings.FrameDouble > 1 ? ", Factor=" + (1 << settings.FrameDouble).ToString() : "",
                                          GetMatrixIn(settings),
                                          FinalResize,
                                          multiThreaded ? "" : ", Engines=1");
                    }
                    IsHD   = false;
                    IsYV24 = false;
                }
            }

            if (settings.DownscaleMethod != DownscaleMethods.SSim)
            {
                DitherPost(Script, ref IsHD, ref IsYV24, settings.IncreaseFrameRate);
            }

            string[] ShaderCommands = new string[] { "SuperRes", "SuperXBR", "SuperResXBR", "ResizeShader" };
            if (settings.CropAfter.HasValue || settings.FrameDouble == 0)
            {
                if (settings.CropAfter.HasValue || settings.SourceAspectRatio != 1 || settings.OutputWidth != settings.SourceWidth || settings.OutputHeight != settings.OutputHeight)
                {
                    if (settings.DownscaleMethod == DownscaleMethods.SSim && settings.FrameDouble == 0)
                    {
                        Script.AppendLine("ResizeShader({0}{1})",
                                          FinalResize.Replace("fWidth=", "").Replace("fHeight=", "").Replace(" f", " "), // Use same string as FinalResize but remove 'f' parameter sufix.
                                          GetMatrixIn(settings));
                    }
                    DitherPost(Script, ref IsHD, ref IsYV24, false);

                    if (settings.CropAfter.HasValue || settings.DownscaleMethod == DownscaleMethods.Bicubic)
                    {
                        Script.LoadPluginAvsi("ResizeX.avsi");
                        bool   ApplyResize = settings.FrameDouble == 0 || !Script.ContainsAny(ShaderCommands);
                        string CropFormat  = "ResizeX";
                        CropFormat += settings.CropAfter.HasValue ? "({0}, {1}, {2}, {3}, -{4}, -{5}{6})" : "({0}, {1}{6})";
                        Script.AppendLine(CropFormat, settings.OutputWidth, settings.OutputHeight,
                                          settings.CropAfter.Left, settings.CropAfter.Top, settings.CropAfter.Right, settings.CropAfter.Bottom,
                                          ApplyResize ? @", kernel=""Bicubic"", a1=0, a2=.75" : "");
                    }
                }
            }

            // Use ColorMatrixShader only if it wasn't already applied through any other shader.
            if (Script.ContainsAny(ShaderCommands))
            {
                // ColorMatrix was applied though another shader.
                Script.Replace("[ColorMatrixShader]" + Environment.NewLine, "");
                Script.LoadPluginDll("Shader.dll");
                Script.LoadPluginAvsi("Shader.avsi");
            }
            else
            {
                string ColorMatrixScript = "";
                // Apply color matrix
                if (settings.SourceColorMatrix == ColorMatrix.Pc709)
                {
                    Script.LoadPluginDll("SmoothAdjust.dll");
                    ColorMatrixScript = string.Format(@"ColorYUV(levels=""PC->TV""");
                }
                else if (settings.SourceColorMatrix != ColorMatrix.Rec709)
                {
                    Script.LoadPluginDll("Shader.dll");
                    Script.LoadPluginAvsi("Shader.avsi");
                    ColorMatrixScript = string.Format(@"ResizeShader(Kernel=""ColorMatrix""{0})", GetMatrixIn(settings));
                }
                Script.Replace("[ColorMatrixShader]" + Environment.NewLine, ColorMatrixScript + Environment.NewLine);
            }

            if (settings.IncreaseFrameRate)
            {
                if (IsYV24)
                {
                    Script.AppendLine(@"ConvertToYUV420()");
                    IsYV24 = false;
                }
                DitherPost(Script, ref IsHD, ref IsYV24, true);
                ApplyInterFrame(Script, settings, CPU);
            }

            if (preview)
            {
                if (settings.Crop)
                {
                    Script.AppendLine("AddBorders(2, 2, 2, 2, $FFFFFF)");
                }
                Script.AppendLine(@"ConvertToRGB32(matrix=""Rec709"")");
            }
            if (multiThreaded)
            {
                Script.AppendLine("Prefetch({0})", CPU);
            }

            if (RunMultiProcesses)
            {
                Script.ConvertToMultiProcesses(settings.SourceFrameRate.Value);
            }
            else
            {
                Script.Cleanup();
            }

            return(Script);
        }
        public CompletionStatus GenerateDeshakerLog(MediaEncoderSettings settings, string inputFile) {
            // Prepare Deshaker settings.
            settings.DeshakerSettings.Pass = 1;
            settings.DeshakerSettings.LogFile = settings.DeshakerTempLog;
            settings.DeshakerSettings.SourcePixelAspectRatio = settings.SourceAspectRatio.Value;
            // settings.DeshakerSettings.AppendToFile = true;
            File.Delete(settings.DeshakerLog);

            // Start UI.
            CompletionStatus Result = CompletionStatus.Success;
            object JobId = "Deshaker";
            FFmpegConfig.UserInterfaceManager.Start(JobId, "Running Deshaker Prescan");
            ProcessStartOptions JobOptions = new ProcessStartOptions(JobId, "Getting Frame Count", false);

            // Get frame count.
            settings.CalculateSize();
            int FrameStart = (int)((settings.DeshakerSettings.PrescanStart ?? 0) * settings.SourceFrameRate.Value);
            int FrameEnd = (int)((settings.DeshakerSettings.PrescanEnd ?? 0) * settings.SourceFrameRate.Value);
            string Script = MediaEncoderScript.GenerateDeshakerScript(settings, inputFile, 0, FrameStart, FrameEnd);
            File.WriteAllText(settings.DeshakerScript, Script);
            JobOptions.FrameCount = AvisynthTools.GetFrameCount(settings.DeshakerScript, JobOptions);

            // Pad file start.
            using (StreamWriter sw = new StreamWriter(File.Open(settings.DeshakerLog, FileMode.Create), Encoding.ASCII)) {
                for (int i = 0; i < FrameStart; i++) {
                    sw.WriteLine((i + 1).ToString().PadLeft(7) + "									skipped		#	   0.00	   0.00	");
                }
            }

            // Run segments.
            var Segments = settings.DeshakerSettings.Segments;
            if (JobOptions.FrameCount > 0) {
                for (int i = 0; i < Segments.Count; i++) {
                    // Get start position of next segment.
                    long NextSegmentStart = i < Segments.Count - 1 ? Segments[i + 1].FrameStart : 0;
                    if (NextSegmentStart == 0 || NextSegmentStart > FrameStart) { // Enforce PrescanStart for preview
                        long SegmentStart = Segments[i].FrameStart;
                        long SegmentEnd = NextSegmentStart > 0 ? NextSegmentStart - 1 : 0;
                        // Enforce PrescanEnd for preview
                        if ((FrameEnd > 0 && SegmentStart > FrameEnd) || (SegmentEnd > 0 && SegmentStart > SegmentEnd))
                            break;
                        if ((FrameStart > 0 && FrameStart > SegmentStart) || SegmentStart == 0)
                            SegmentStart = FrameStart;
                        if ((FrameEnd > 0 && FrameEnd < SegmentEnd) || SegmentEnd == 0)
                            SegmentEnd = FrameEnd;
                        Result = GenerateDeshakerLogSegment(settings, inputFile, i, FrameStart, SegmentStart, SegmentEnd, JobOptions);
                        if (Result != CompletionStatus.Success)
                            break;

                        // Merge log segment into log file and set right frame numbers.
                        using (StreamWriter sw = new StreamWriter(File.Open(settings.DeshakerLog, FileMode.Append), Encoding.ASCII)) {
                            using (StreamReader sr = new StreamReader(File.OpenRead(settings.DeshakerTempLog), Encoding.ASCII)) {
                                string LogLine, LogNum, LogNumField, LineOut;
                                long NewLineNum = SegmentStart;
                                LogLine = sr.ReadLine();
                                while (LogLine != null) {
                                    if (LogLine.Length > 7) {
                                        LogNum = LogLine.Substring(0, 7).Trim();
                                        if (LogNum.Length > 0) {
                                            LogNumField = LogNum[LogNum.Length - 1].ToString();
                                            if (LogNumField != "A" && LogNumField != "B") // For interlaced videos
                                                LogNumField = "";
                                            NewLineNum++; // Log file starts at 1, not 0.
                                            LineOut = (NewLineNum.ToString() + LogNumField).PadLeft(7) + LogLine.Substring(7, LogLine.Length - 8);
                                            sw.WriteLine(LineOut);
                                        }
                                    }
                                    LogLine = sr.ReadLine();
                                }
                            }
                        }
                        File.Delete(settings.DeshakerTempLog);
                    }
                }
            } else
                Result = CompletionStatus.Error;

            // End UI.
            FFmpegConfig.UserInterfaceManager.Stop(JobId);
            return Result;
        }
 private async Task GetMediaInfo(string previewFile, MediaEncoderSettings settings) {
     using (MediaInfoReader InfoReader = new MediaInfoReader()) {
         await InfoReader.LoadInfoAsync(previewFile);
         settings.SourceWidth = InfoReader.Width;
         settings.SourceHeight = InfoReader.Height;
         settings.SourceAspectRatio = InfoReader.PixelAspectRatio ?? 1;
         if (settings.SourceAspectRatio != 1) {
             // Get aspect ratio from FFMPEG which is more accurate.
             float? SAR = FfmpegBusiness.GetPixelAspectRatio(settings);
             if (SAR.HasValue)
                 settings.SourceAspectRatio = SAR.Value;
         }
         // Fix last track of VCDs that is widescreen.
         if (settings.SourceHeight == 288 && settings.SourceWidth == 352 && settings.SourceAspectRatio == 1.485f)
         settings.SourceAspectRatio = 1.092f;
         settings.SourceFrameRate = InfoReader.FrameRate;
         if (settings.ConvertToAvi)
             await InfoReader.LoadInfoAsync(Settings.NaturalGroundingFolder + settings.FileName);
         settings.SourceAudioFormat = InfoReader.AudioFormat;
         settings.SourceVideoFormat = InfoReader.VideoFormat;
         settings.SourceColorMatrix = InfoReader.Height < 720 ? ColorMatrix.Rec601 : ColorMatrix.Rec709;
         if (!settings.CanCopyAudio)
             settings.EncodeFormat = VideoFormats.Mkv;
         settings.SourceAudioBitrate = InfoReader.AudioBitRate;
         settings.SourceBitDepth = InfoReader.BitDepth;
         settings.Position = (InfoReader.Length ?? 0) / 2;
         settings.CalculateSize();
     }
 }
        public AviSynthScriptBuilder GenerateVideoScript(MediaEncoderSettings settings, string inputFile, bool preview, bool multiThreaded) {
            int CPU = Environment.ProcessorCount;
            if (CPU <= 1)
                multiThreaded = false;
            bool AviSynthPlus = (Settings.EncoderAviSynthVersion == AviSynthVersion.AviSynthPlus);
            // multiThreaded = true;

            settings.CalculateSize();

            // Calculate encoding and final frame rates.
            double ChangeSpeedValue = settings.ChangeSpeed ? (double)settings.ChangeSpeedValue / 100 : 1;
            double FrameRateBefore = settings.SourceFrameRate.Value * ChangeSpeedValue;

            // Generate video script.
            AviSynthScriptBuilder Script = new AviSynthScriptBuilder();
            bool IsYV24 = false;
            Script.AppendLine(); // After clean-up, this adds a line after LoadPlugin commands.
            Script.AddPluginPath();
            if (multiThreaded) {
                // Script.AppendLine("Setmemorymax(1500)");
                if (AviSynthPlus) {
                    Script.LoadPluginAvsi("AviSynthMT.avsi");
                    //Script.AppendLine(@"SetFilterMTMode(""DEFAULT_MT_MODE"",2)");
                    //Script.AppendLine(@"SetFilterMTMode(""LWLibavVideoSource"",3)");
                    //Script.AppendLine(@"SetFilterMTMode(""LWLibavAudioSource"",3)");
                    //if (settings.Denoise1)
                    //    Script.AppendLine(@"SetFilterMTMode(""KNLMeansCL"",3)");
                } else {
                    Script.AppendLine("SetMTMode(3,{0})", CPU);
                }
            }
            if (settings.ConvertToAvi || inputFile.ToLower().EndsWith(".avi"))
                Script.OpenAvi(inputFile, !string.IsNullOrEmpty(settings.SourceAudioFormat));
            else
                Script.OpenDirect(inputFile, null, !string.IsNullOrEmpty(settings.SourceAudioFormat), 1);
            if (FrameRateBefore != settings.SourceFrameRate)
                Script.AppendLine(CultureInfo.InvariantCulture, "AssumeFPS({0}, true)", FrameRateBefore);
            if (settings.Trim) {
                Script.AppendLine("Trim({0}, {1})",
                    (settings.TrimStart ?? 0) > 0 ? (int)(settings.TrimStart.Value * settings.SourceFrameRate.Value) : 0,
                    (settings.TrimEnd ?? 0) > 0 && !preview ? (int)(settings.TrimEnd.Value * settings.SourceFrameRate.Value) : 0);
            }
            if (settings.CropSource.HasValue) {
                Script.AppendLine("Crop({0}, {1}, -{2}, -{3})", settings.CropSource.Left, settings.CropSource.Top, settings.CropSource.Right, settings.CropSource.Bottom);
            }
            if (settings.Denoise1) {
                if (GpuSupport == SupportedOpenClVersion.v12)
                    Script.LoadPluginDll("KNLMeansCL.dll");
                else
                    Script.LoadPluginDll("KNLMeansCL-6.11.dll");
                Script.AppendLine("ConvertToYV24()");
                IsYV24 = true;
                if (multiThreaded && !AviSynthPlus)
                    Script.AppendLine("SetMTMode(5)");
                Script.AppendLine(CultureInfo.InvariantCulture, @"KNLMeansCL(D=1, A=2, h={0}, cmode=true, device_type=""{1}""{2})", 
                    ((double)settings.Denoise1Strength / 10).ToString(CultureInfo.InvariantCulture), 
                    GpuSupport != SupportedOpenClVersion.None ? "GPU" : "CPU",
                    GpuSupport != SupportedOpenClVersion.None ? ", device_id=" + Settings.SavedFile.GraphicDeviceId.ToString() : "");
            }
            if (multiThreaded && !AviSynthPlus)
                Script.AppendLine("SetMTMode(2)");
            if (settings.FrameDouble > 0 || settings.SourceColorMatrix == ColorMatrix.Rec601) {
                Script.LoadPluginDll("Shaders\\Shader.dll");
                Script.LoadPluginAvsi("Shaders\\Shader.avsi");
            }
            bool HasNoShader = (!settings.SuperRes && settings.UpscaleMethod == UpscaleMethods.NNedi3 && settings.DownscaleMethod == DownscaleMethods.Bicubic);
            if (settings.SourceColorMatrix == ColorMatrix.Rec601 && settings.FrameDouble == 0 || HasNoShader) {
                Script.AppendLine("ColorMatrixShader(MatrixIn=\"601\")");
            }
            if (settings.Denoise2) {
                Script.LoadPluginDll("FFT3DFilter.dll");
                Script.AppendLine(CultureInfo.InvariantCulture, @"fft3dfilter(sigma={0}, bt=5, bw=48, bh=48, ow=24, oh=24, sharpen={1})",
                    ((double)settings.Denoise2Strength / 10).ToString(CultureInfo.InvariantCulture),
                    (double)settings.Denoise2Sharpen / 100);
            }

            if (settings.FrameDouble > 0) {
                string FinalSize = string.Format("fWidth={0}, fHeight={1}",
                    settings.OutputWidth + settings.CropAfter.Left + settings.CropAfter.Right,
                    settings.OutputHeight + settings.CropAfter.Top + settings.CropAfter.Bottom);
                string FinalResize = FinalSize;
                if (settings.DownscaleMethod == DownscaleMethods.SSim)
                    FinalResize += string.Format(@", fKernel=""SSim"", fB={0}{1}",
                        settings.SSimStrength / 100, settings.SSimSoft ? ", fC=1" : "");
                else // DownscaleMethod == Bicubic
                    FinalResize += string.Format(@", fKernel=""Bicubic"", fB=0, fC=.75");

                bool IsLastDouble = false;
                if (settings.UpscaleMethod == UpscaleMethods.NNedi3) {
                    if (IsYV24) {
                        Script.AppendLine("ConvertToYV12()");
                        IsYV24 = false;
                    }
                    Script.LoadPluginDll("nnedi3.dll");
                    //Script.LoadPluginDll("FTurn.dll");
                    Script.LoadPluginAvsi("edi_rpow2.avsi");

                    for (int i = 0; i < settings.FrameDouble; i++) {
                        IsLastDouble = i == settings.FrameDouble - 1;
                        string DoubleScript = string.Format("edi_rpow2(2, nns=4, {0}, Threads=2)",
                            IsLastDouble && settings.DownscaleMethod == DownscaleMethods.Bicubic ? @"cshift=""Bicubic"", a1=0, a2=.75, " + FinalSize : @"cshift=""Spline16Resize""");
                        if (settings.SuperRes) {
                            Script.AppendLine(CultureInfo.InvariantCulture, @"SuperRes({0}, {1}, {2}, """"""{3}""""""{4}{5})",
                                settings.SuperRes3Passes ? (i == 0 && settings.FrameDouble > 1 ? 5 : 3) : 2, 
                                settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f, DoubleScript,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim ? ", " + FinalResize : "");
                        } else {
                            Script.AppendLine(DoubleScript);
                            if (IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim) {
                                Script.AppendLine("SSimDownscaler({0}{1})", 
                                    FinalResize.Replace(" f", " ").Replace("fW", "W"), // Use same string as FinalResize but remove 'f' parameter sufix.
                                    settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "");
                            }
                        }
                        if (i == 0 && settings.IncreaseFrameRate)
                            ApplyInterFrame(Script, settings, CPU);
                    }
                } else { // UpscaleMethod == SuperXBR
                    for (int i = 0; i < settings.FrameDouble; i++) {
                        IsLastDouble = i == settings.FrameDouble - 1;
                        if (settings.SuperRes) {
                            Script.AppendLine(CultureInfo.InvariantCulture, @"SuperResXBR({0}, {1}, {2}, XbrStr={3}, XbrSharp={4}{5}{6})",
                                settings.SuperRes3Passes ? (i == 0 && settings.FrameDouble > 1 ? 5 : 3) : 2,
                                settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f,
                                settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble ? ", " + FinalResize : "");
                        } else {
                            Script.AppendLine("SuperXBR(Str={0}, Sharp={1}{2}{3})",
                                settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble ? ", " + FinalResize : "");
                        }
                        if (i == 0 && settings.IncreaseFrameRate) {
                            if (IsYV24) {
                                Script.AppendLine("ConvertToYV12()");
                                IsYV24 = false;
                            }
                            ApplyInterFrame(Script, settings, CPU);
                        }
                    }
                }
            }
            if (IsYV24) {
                Script.AppendLine("ConvertToYV12()");
                IsYV24 = false;
            }
            if (settings.FrameDouble == 0 && settings.IncreaseFrameRate)
                ApplyInterFrame(Script, settings, CPU);

            Script.LoadPluginAvsi("ResizeX.avsi");
            if (settings.CropAfter.HasValue || settings.FrameDouble == 0) {
                bool ApplyResize = settings.FrameDouble == 0 || HasNoShader;
                string CropFormat = "ResizeX";
                CropFormat += settings.CropAfter.HasValue ? "({0}, {1}, {2}, {3}, -{4}, -{5}{6})" : "({0}, {1}{6})";
                Script.AppendLine(CropFormat, settings.OutputWidth, settings.OutputHeight,
                    settings.CropAfter.Left, settings.CropAfter.Top, settings.CropAfter.Right, settings.CropAfter.Bottom,
                    ApplyResize ? @", kernel=""Bicubic"", a1=0, a2=.75" : "");
            }

            if (preview) {
                if (settings.Crop)
                    Script.AppendLine("AddBorders(2, 2, 2, 2, $FFFFFF)");
                Script.AppendLine(@"ConvertToRGB32(matrix=""Rec709"")");
            }
            if (multiThreaded && AviSynthPlus)
                Script.AppendLine("Prefetch({0})", CPU);

            Script.Cleanup();
            return Script;
        }