/// <summary>
        /// Generates AviSynth script used for video encoding
        /// </summary>
        /// <param name="videoInfo">All video properties</param>
        /// <param name="changeFps">Defines whether framerate should be changed</param>
        /// <param name="targetFps">Sets target framerate</param>
        /// <param name="resizeTo">Sets target video resolution</param>
        /// <param name="stereoEncoding">Defines, which stereo encoding mode should be used</param>
        /// <param name="stereoVideoInfo">Sets all parameters for stereo encoding</param>
        /// <param name="isDvdResolution">Defines whether target resolution is used for DVD encoding</param>
        /// <param name="subtitleFile">Sets subtitle file for hardcoding into video</param>
        /// <param name="subtitleOnlyForced">Defines whether only forced captions should be hardcoded</param>
        /// <param name="skipScaling"></param>
        /// <returns>Path to AviSynth script</returns>
        public string Generate(VideoInfo videoInfo, bool changeFps, float targetFps, Size resizeTo,
                               StereoEncoding stereoEncoding, StereoVideoInfo stereoVideoInfo, bool isDvdResolution,
                               string subtitleFile, bool subtitleOnlyForced, bool skipScaling)
        {
            var sb = new StringBuilder();

            var mtUseful = (videoInfo.Interlaced && _appConfig.UseHQDeinterlace) || changeFps;

            var useStereo = stereoEncoding != StereoEncoding.None && stereoVideoInfo.RightStreamId > -1;

            // support for multithreaded AviSynth
            if (_appConfig.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(2,0)");
                sb.AppendLine("SetMemoryMax(512)");
            }

            var pluginList = new List <string> {
                "ffms2.dll"
            };
            var scriptList = new List <string>();

            //loading plugins

            if (changeFps || (videoInfo.Interlaced && _appConfig.UseHQDeinterlace))
            {
                pluginList.Add("mvtools2.dll");
            }

            if (videoInfo.Interlaced && _appConfig.UseHQDeinterlace)
            {
                pluginList.Add(_appConfig.LastAviSynthVer.StartsWith("2.5")
                                    ? "mt_masktools-25.dll"
                                    : "mt_masktools-26.dll");
                pluginList.Add("nnedi3.dll");
                pluginList.Add("RemoveGrainSSE2.dll");
                pluginList.Add("RepairSSE2.dll");

                scriptList.Add("QTGMC-3.32.avsi");
            }
            else if (videoInfo.Interlaced)
            {
                pluginList.Add("Decomb.dll");
            }

            if (useStereo)
            {
                pluginList.Add("H264StereoSource.dll");
            }

            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                case "sup":
                    pluginList.Add("SupTitle.dll");
                    break;

                case "ass":
                case "ssa":
                case "srt":
                    pluginList.Add("VSFilter.dll");
                    break;
                }
            }

            // generate plugin and script loading
            foreach (var plugin in pluginList)
            {
                sb.AppendLine($"LoadPlugin(\"{Path.Combine(_appConfig.AvsPluginsPath, plugin)}\")");
            }
            foreach (var script in scriptList)
            {
                sb.AppendLine($"Import(\"{Path.Combine(_appConfig.AvsPluginsPath, script)}\")");
            }

            //generate rest of the script

            // calculate framerate numerator & denominator
            if (videoInfo.Fps <= 0)
            {
                var mi = new MediaInfoContainer();
                try
                {
                    mi = GenHelper.GetMediaInfo(videoInfo.TempFile);
                }
                catch (TimeoutException ex)
                {
                    Log.Error(ex);
                    mi = new MediaInfoContainer();
                }
                finally
                {
                    if (mi.Video.Count > 0)
                    {
                        videoInfo.Fps = mi.Video[0].FrameRate;
                        VideoHelper.GetFpsNumDenom(videoInfo.Fps, out videoInfo.FrameRateEnumerator,
                                                   out videoInfo.FrameRateDenominator);

                        if (videoInfo.FrameRateEnumerator == 0)
                        {
                            videoInfo.FrameRateEnumerator  = (int)Math.Round(videoInfo.Fps) * 1000;
                            videoInfo.FrameRateDenominator =
                                (int)(Math.Round(Math.Ceiling(videoInfo.Fps) - Math.Floor(videoInfo.Fps)) + 1000);
                        }
                    }
                }
            }
            sb.Append($"FFVideoSource(\"{videoInfo.TempFile}\",");

            if (videoInfo.FrameRateEnumerator > 0 && videoInfo.FrameRateDenominator > 0)
            {
                sb.Append($"fpsnum={videoInfo.FrameRateEnumerator:0},fpsden={videoInfo.FrameRateDenominator:0},");
            }

            var threadCount = _appConfig.LimitDecoderThreads ? 1 : 0;

            sb.Append($"threads={threadCount:0})");
            sb.AppendLine();

            var stereoVar = string.Empty;

            if (useStereo)
            {
                var configFile = GenerateStereoSourceConfig(stereoVideoInfo);
                sb.AppendLine($"VideoRight = H264StereoSource(\"{configFile}\",{videoInfo.FrameCount - 50:0})");
                StereoConfigFile = configFile;
                stereoVar        = "VideoRight";
            }

            // deinterlace video source
            if (videoInfo.Interlaced)
            {
                if (_appConfig.UseHQDeinterlace)
                {
                    sb.AppendLine("QTGMC(Preset=\"Slower\")");
                }
                else
                {
                    sb.AppendLine("ConvertToYUY2(interlaced=true)");
                    sb.AppendLine("Telecide(post=4)");
                    sb.AppendLine("Crop(4, 0, -4, 0)");
                    sb.AppendLine("AddBorders(4, 0, 4, 0)");
                    sb.AppendLine("ConvertToYV12()");
                }
            }

            // hardcode subtitles
            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                case "sup":
                    var subForced = subtitleOnlyForced ? "true" : "false";
                    sb.Append($"SupTitle(\"{subtitleFile}\", forcedOnly={subForced})");
                    break;

                case "ass":
                case "ssa":
                case "srt":
                    sb.Append($"TextSub(\"{subtitleFile}\")");
                    break;
                }

                sb.AppendLine();
            }

            // video cropping
            if (!videoInfo.CropRect.IsEmpty && !skipScaling)
            {
                int temp;

                Math.DivRem(videoInfo.CropRect.X, 2, out temp);
                videoInfo.CropRect.X += temp;
                Math.DivRem(videoInfo.CropRect.Y, 2, out temp);
                videoInfo.CropRect.Y += temp;
                Math.DivRem(videoInfo.CropRect.Width, 2, out temp);
                videoInfo.CropRect.Width += temp;
                Math.DivRem(videoInfo.CropRect.Height, 2, out temp);
                videoInfo.CropRect.Height += temp;

                videoInfo.Height = videoInfo.CropRect.Height;
                videoInfo.Width  = videoInfo.CropRect.Width;

                if ((videoInfo.CropRect.X > 0) || (videoInfo.CropRect.Y > 0) || (videoInfo.CropRect.Width < videoInfo.Width) ||
                    (videoInfo.CropRect.Height < videoInfo.Height))
                {
                    sb.Append(useStereo ? "CroppedVideoRight = Crop(VideoRight," : "Crop(");

                    sb.Append($"{videoInfo.CropRect.Left:0},{videoInfo.CropRect.Top:0},");
                    sb.Append($"{videoInfo.CropRect.Width:0},{videoInfo.CropRect.Height:0})");
                    sb.AppendLine();

                    if (useStereo)
                    {
                        stereoVar = "CroppedVideoRight";
                    }
                }
            }

            // Side-By-Side stereo encoding
            if (!string.IsNullOrEmpty(stereoVar))
            {
                switch (stereoEncoding)
                {
                case StereoEncoding.FullSideBySideLeft:
                case StereoEncoding.HalfSideBySideLeft:
                    sb.AppendLine($"StackHorizontal(last,{stereoVar})");
                    break;

                case StereoEncoding.FullSideBySideRight:
                case StereoEncoding.HalfSideBySideRight:
                    sb.AppendLine($"StackHorizontal({stereoVar},last)");
                    break;
                }
                sb.AppendLine("ConvertToYV12()");
            }

            var calculatedHeight = videoInfo.Height;
            var calculatedWidth  = videoInfo.Width;

            var borderRight  = 0;
            var borderLeft   = 0;
            var borderBottom = 0;
            var borderTop    = 0;
            var addBorders   = false;

            // video resizing
            if (!resizeTo.IsEmpty && (resizeTo.Height != videoInfo.Height || resizeTo.Width != videoInfo.Width) && !skipScaling)
            {
                // aspect ratios

                var toAr   = (float)Math.Round(resizeTo.Width / (float)resizeTo.Height, 3);
                var fromAr = videoInfo.AspectRatio;
                var mod    = 1f;

                calculatedWidth = resizeTo.Width;

                if (fromAr > toAr) // source aspectratio higher than target aspectratio
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                        }
                        calculatedWidth = 720;
                    }
                    else
                    {
                        calculatedWidth  = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else if (Math.Abs(fromAr - toAr) <= 0)  // source and target aspectratio equals
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        calculatedWidth  = 720;
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                        }
                    }
                    else
                    {
                        calculatedWidth  = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / toAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else
                {
                    if (fromAr > 1.4f && isDvdResolution)  // source aspectratio not 4:3, encoding for dvd resolution
                    {
                        mod = 720f / resizeTo.Width;

                        calculatedHeight = (int)(calculatedWidth / fromAr);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                            calculatedWidth  = (int)(calculatedHeight * fromAr * mod);
                        }
                        else
                        {
                            calculatedWidth = 720;
                        }
                    }
                    else if (isDvdResolution)
                    {
                        calculatedHeight = resizeTo.Height;
                        calculatedWidth  = (int)(calculatedHeight * fromAr);
                    }
                    else
                    {
                        calculatedHeight = resizeTo.Height;
                    }

                    int temp;
                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (Math.Abs(toAr - 1.778f) <= 0)     // aspectratio 16:9
                    {
                        addBorders = true;
                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;

                        var borderWidth = (int)((resizeTo.Width * mod) - calculatedWidth);
                        borderLeft = borderWidth / 2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;
                    }
                    else if (calculatedWidth != resizeTo.Width)
                    {
                        addBorders = true;
                        var borderWidth = resizeTo.Width - calculatedWidth;
                        borderLeft = borderWidth / 2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;

                        var borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight / 2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop   += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
            }

            // apply resize filter
            if (calculatedHeight != videoInfo.Height || calculatedWidth != videoInfo.Width ||
                (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                 stereoEncoding == StereoEncoding.HalfSideBySideRight &&
                 useStereo) && !skipScaling)
            {
                if (calculatedHeight < videoInfo.Height || calculatedWidth < videoInfo.Width ||
                    (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                     stereoEncoding == StereoEncoding.HalfSideBySideRight &&
                     useStereo))
                {
                    sb.Append("BicubicResize");
                }
                else
                {
                    sb.Append("Lanczos4Resize");
                }

                sb.Append($"({calculatedWidth:0},{calculatedHeight:0})");
                sb.AppendLine();
            }

            // add borders if needed
            if (addBorders && (borderLeft > 0 || borderRight > 0 || borderTop > 0 || borderBottom > 0) && !skipScaling)
            {
                sb.AppendLine($"AddBorders({borderLeft:0},{borderTop:0},{borderRight:0},{borderBottom:0})");
            }

            // change framerate
            if (changeFps)
            {
                int fpsnum;
                int fpsden;

                // get framerate numerator & denominator for target framerate
                VideoHelper.GetFpsNumDenom(targetFps, out fpsnum, out fpsden);

                // source is 23.976 or 24 fps
                if (videoInfo.FrameRateEnumerator == 24000 && (videoInfo.FrameRateDenominator == 1001 || videoInfo.FrameRateDenominator == 1000))
                {
                    if (fpsnum == 30000 && fpsden == 1001)
                    {
                        // 3:2 pulldown / telecine
                        sb.AppendLine("AssumeFrameBased()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        sb.AppendLine("Weave()");
                    }
                    else if (fpsnum == 25000 && fpsden == 1000)
                    {
                        // convert to 25 fps
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(50)");
                        sb.AppendLine("AssumeTFF()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(4,0,3)");
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // source is 30fps
                else if (videoInfo.FrameRateEnumerator == 30000)
                {
                    sb.AppendLine("ConvertToYUY2()");
                    sb.AppendLine("DoubleWeave()");
                    sb.AppendLine($"ConvertFPS(numerator={fpsnum * 2:0},denominator={fpsden:0})");
                    sb.AppendLine("SelectEven()");
                    sb.AppendLine("ConvertToYV12()");
                }
                // source is 25fps
                else if (videoInfo.FrameRateEnumerator == 25000 && videoInfo.FrameRateDenominator == 1000)
                {
                    if ((fpsnum == 30000 || fpsnum == 24000) && fpsden == 1001)
                    {
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(numerator=48000,denominator=1001");
                        if (fpsnum == 30000)
                        {
                            sb.AppendLine("AssumeFrameBased()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        }
                        else
                        {
                            sb.AppendLine("AssumeTFF()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEven()");
                        }
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // every other framerate
                else
                {
                    // very slow framerate interpolation
                    sb.AppendLine("super = MSuper(pel=2)");
                    sb.AppendLine("backward_vec = MAnalyse(super, overlap=4, isb = true, search=3)");
                    sb.AppendLine("forward_vec = MAnalyse(super, overlap=4, isb = false, search=3)");
                    sb.Append($"MFlowFps(super, backward_vec, forward_vec, num={fpsnum:0}, den={fpsden:0})");
                }

                sb.AppendLine();
            }

            // multithreaded avisynth
            if (!_appConfig.UseAviSynthMT || !mtUseful)
            {
                return(WriteScript(sb.ToString()));
            }

            sb.AppendLine("SetMTMode(1)");
            sb.AppendLine("GetMTMode(false) > 0 ? distributor() : last");

            return(WriteScript(sb.ToString()));
        }
        /// <summary>
        /// Generates commandline arguments used for encoding an video stream to h.264 format.
        /// Input is either stdin or file/avisynth script.
        /// </summary>
        /// <param name="inProfile">Encoding profile</param>
        /// <param name="bitrate">Target bitrate</param>
        /// <param name="hRes">Video width</param>
        /// <param name="vRes">Video height</param>
        /// <param name="pass">Encoding pass</param>
        /// <param name="fpsN">Framerate numerator</param>
        /// <param name="fpsD">Framerate denominator</param>
        /// <param name="stereo">Defines, which stereo encoding mode should be used</param>
        /// <param name="format">Image format</param>
        /// <param name="inFile">Path to input file</param>
        /// <param name="outFile">Path to output file</param>
        /// <returns>Commandline arguments</returns>
        public static string Generate(X264Profile inProfile, int bitrate, int hRes, int vRes, int pass, int fpsN, int fpsD, StereoEncoding stereo = StereoEncoding.None,
                                      VideoFormat format = VideoFormat.Unknown, string inFile = "input", string outFile = "output")
        {
            StringBuilder sb = new StringBuilder();
            if (inProfile != null)
            {
                bool display;
                X264Device device = X264Device.CreateDeviceList()[inProfile.TuneDevice];

                // AVC Profiles
                switch (inProfile.AVCProfile)
                {
                    case 0:
                        sb.Append("--profile baseline ");
                        break;
                    case 1:
                        sb.Append("--profile main ");
                        break;
                    default:
                        sb.Append("--profile high ");
                        break;
                }

                // AVC Levels
                if (inProfile.AVCLevel != 15) // unrestricted
                    sb.AppendFormat("--level {0} ", CLILevelNames[inProfile.AVCLevel]);

                // Blu-Ray compatibility
                if (inProfile.UseBluRayCompatibility)
                    sb.Append("--bluray-compat ");

                // x264 Presets
                if (!inProfile.CustomCommandLine.Contains("--preset"))
                {
                    switch (inProfile.Preset)
                    {
                        case 0: sb.Append("--preset ultrafast "); break;
                        case 1: sb.Append("--preset superfast "); break;
                        case 2: sb.Append("--preset veryfast "); break;
                        case 3: sb.Append("--preset faster "); break;
                        case 4: sb.Append("--preset fast "); break;
                        //case 5: sb.Append("--preset medium "); break; // default value
                        case 6: sb.Append("--preset slow "); break;
                        case 7: sb.Append("--preset slower "); break;
                        case 8: sb.Append("--preset veryslow "); break;
                        case 9: sb.Append("--preset placebo "); break;
                    }
                }

                // x264 Tunings
                if (!inProfile.CustomCommandLine.Contains("--tune"))
                {
                    switch (inProfile.Tuning)
                    {
                        case 1: sb.Append("--tune film "); break;
                        case 2: sb.Append("--tune animation "); break;
                        case 3: sb.Append("--tune grain "); break;
                        case 4: sb.Append("--tune psnr "); break;
                        case 5: sb.Append("--tune ssim "); break;
                        case 6: sb.Append("--tune fastdecode "); break;
                    }
                }

                // Encoding Modes
                int tempPass = pass;

                int tempBitrate = bitrate;
                int vbvBuf = GetVBVMaxrate(inProfile, device);

                if (tempBitrate <= 0)
                    tempBitrate = inProfile.VBRSetting;

                if (vbvBuf > 0 && tempBitrate > vbvBuf)   // limit Bitrate to max vbvbuf size
                    tempBitrate = vbvBuf;

                switch (inProfile.EncodingMode)
                {
                    case 0: // ABR
                        if (!inProfile.CustomCommandLine.Contains("--bitrate"))
                            sb.AppendFormat(AppSettings.CInfo, "--bitrate {0:0} ", tempBitrate);
                        break;
                    case 1: // Constant Quantizer
                        if (!inProfile.CustomCommandLine.Contains("--qp"))
                            sb.AppendFormat(AppSettings.CInfo, "--qp {0:0}", inProfile.QuantizerSetting);
                        break;
                    case 2: // automated 2 pass
                    case 3: // automated 3 pass
                        sb.AppendFormat(AppSettings.CInfo, "--pass {0:0} --bitrate {1:0} ", tempPass, tempBitrate);
                        break;
                    default:
                        if (!inProfile.CustomCommandLine.Contains("--crf") && inProfile.QualitySetting != 23)
                            sb.AppendFormat(AppSettings.CInfo, "--crf {0:0} ", inProfile.QualitySetting);
                        break;
                }

                // Slow 1st Pass
                if (!inProfile.CustomCommandLine.Contains("--slow-firstpass"))
                    if ((inProfile.UseSlowFirstPass) && inProfile.Preset < 9 && // 9 = placebo
                       ((inProfile.EncodingMode == 2) || // automated twopass
                        (inProfile.EncodingMode == 3)))  // automated threepass
                        sb.Append("--slow-firstpass ");

                // Threads
                if (!inProfile.CustomCommandLine.Contains("--thread-input"))
                    if (inProfile.UseThreadInput && inProfile.NumThreads == 1)
                        sb.Append("--thread-input ");
                if (!inProfile.CustomCommandLine.Contains("--threads"))
                    if (inProfile.NumThreads > 0)
                        sb.AppendFormat(AppSettings.CInfo, "--threads {0:0} ", inProfile.NumThreads);

                #region frame-type tab

                // H.264 Features
                if (inProfile.UseDeblocking)
                {
                    display = false;
                    switch (inProfile.Tuning)
                    {
                        case 1: if (inProfile.DeblockingStrength != -1 || inProfile.DeblockingThreshold != -1) display = true; break; // film
                        case 2: if (inProfile.DeblockingStrength != 1 || inProfile.DeblockingThreshold != 1) display = true; break; // animation
                        case 3: if (inProfile.DeblockingStrength != -2 || inProfile.DeblockingThreshold != -2) display = true; break; // grain
                        default: if (inProfile.DeblockingStrength != 0 || inProfile.DeblockingThreshold != 0) display = true;
                            break;
                    }

                    if (!inProfile.CustomCommandLine.Contains("--deblock "))
                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--deblock {0:0}:{1:0} ", inProfile.DeblockingStrength,
                                            inProfile.DeblockingThreshold);
                }
                else
                {
                    if (!inProfile.CustomCommandLine.Contains("--no-deblock"))
                        if (inProfile.Preset != 0 && inProfile.Tuning != 7) // ultrafast preset and not fast decode tuning
                            sb.Append("--no-deblock ");
                }

                if (inProfile.AVCProfile > 0 && !inProfile.CustomCommandLine.Contains("--no-cabac"))
                {
                    if (!inProfile.UseCabac)
                    {
                        if (inProfile.Preset != 0 && inProfile.Tuning != 7) // ultrafast preset and not fast decode tuning
                            sb.Append("--no-cabac ");
                    }
                }

                // GOP Size
                int backupMaxGopSize = inProfile.MaxGopSize;
                int backupMinGopSize = inProfile.MinGopSize;

                inProfile.MaxGopSize = GetKeyInt(fpsN, fpsD, backupMaxGopSize, device, inProfile.GopCalculation);

                if (inProfile.MaxGopSize != 250) // default size
                {
                    if (inProfile.MaxGopSize == 0)
                        sb.Append("--keyint infinite ");
                    else
                        sb.AppendFormat(AppSettings.CInfo, "--keyint {0:0} ", inProfile.MaxGopSize);
                }

                if (!inProfile.UseBluRayCompatibility)
                {
                    inProfile.MinGopSize = GetMinKeyInt(fpsN, fpsD, backupMinGopSize, inProfile.MaxGopSize, device,
                                                        inProfile.GopCalculation);
                    if (inProfile.MinGopSize > (inProfile.MaxGopSize / 2 + 1))
                    {
                        inProfile.MinGopSize = inProfile.MaxGopSize / 2 + 1;
                    }
                    int Default = Math.Min(inProfile.MaxGopSize / 10, fpsN / fpsD);

                    if (inProfile.MinGopSize != Default) // (MIN(--keyint / 10,--fps)) is default
                        sb.AppendFormat(AppSettings.CInfo, "--min-keyint {0:0} ", inProfile.MinGopSize);
                }

                inProfile.MaxGopSize = backupMaxGopSize;
                inProfile.MinGopSize = backupMinGopSize;

                if (!inProfile.CustomCommandLine.Contains("--open-gop") && (inProfile.UseOpenGop || inProfile.UseBluRayCompatibility))
                    sb.Append("--open-gop ");

                // B-Frames
                inProfile.NumBFrames = GetBFrames(inProfile, device);
                if (inProfile.AVCProfile > 0 && inProfile.NumBFrames != X264Settings.GetDefaultNumberOfBFrames(inProfile.AVCLevel, inProfile.Tuning, inProfile.AVCProfile, device))
                    sb.AppendFormat(AppSettings.CInfo, "--bframes {0:0} ", inProfile.NumBFrames);

                if (inProfile.NumBFrames > 0)
                {
                    if (!inProfile.CustomCommandLine.Contains("--b-adapt"))
                    {
                        display = false;
                        if (inProfile.Preset > 5) // medium
                        {
                            if (inProfile.AdaptiveBFrames != 2)
                                display = true;
                        }
                        else if (inProfile.Preset > 0) // ultrafast
                        {
                            if (inProfile.AdaptiveBFrames != 1)
                                display = true;
                        }
                        else
                        {
                            if (inProfile.AdaptiveBFrames != 0)
                                display = true;
                        }
                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--b-adapt {0:0} ", inProfile.AdaptiveBFrames);
                    }

                    inProfile.BPyramid = GetBPyramid(inProfile, device);
                    if (inProfile.NumBFrames > 1 && (inProfile.BPyramid != 2 && !inProfile.UseBluRayCompatibility || inProfile.BPyramid != 1 && inProfile.UseBluRayCompatibility))
                    {
                        switch (inProfile.BPyramid) // pyramid needs a minimum of 2 b frames
                        {
                            case 1: sb.Append("--b-pyramid strict "); break;
                            case 0: sb.Append("--b-pyramid none "); break;
                        }
                    }

                    if (!inProfile.CustomCommandLine.Contains("--no-weightb"))
                        if (!inProfile.UseWeightedPred && inProfile.Tuning != 7 && inProfile.Preset != 0) // no weightpredb + tuning != fastdecode + preset != ultrafast
                            sb.Append("--no-weightb ");
                }

                // B-Frames bias
                if (!inProfile.CustomCommandLine.Contains("--b-bias "))
                    if (inProfile.BFrameBias != 0)
                        sb.AppendFormat(AppSettings.CInfo, "--b-bias {0:0} ", inProfile.BFrameBias);

                // Other
                if (inProfile.UseAdaptiveIFrameDecision)
                {
                    if (!inProfile.CustomCommandLine.Contains("--scenecut "))
                        if (inProfile.NumExtraIFrames != 40 && inProfile.Preset != 0 ||
                            inProfile.NumExtraIFrames != 0 && inProfile.Preset == 0)
                            sb.AppendFormat(AppSettings.CInfo, "--scenecut {0:0} ", inProfile.NumExtraIFrames);
                }
                else
                {
                    if (!inProfile.CustomCommandLine.Contains("--no-scenecut"))
                        if (inProfile.Preset != 0)
                            sb.Append("--no-scenecut ");
                }

                // reference frames
                int iRefFrames = GetRefFrames(hRes, vRes, inProfile, device);
                if (iRefFrames != X264Settings.GetDefaultNumberOfRefFrames(inProfile.Preset, inProfile.Tuning, null, inProfile.AVCLevel, hRes, vRes))
                    sb.AppendFormat(AppSettings.CInfo, "--ref {0:0} ", iRefFrames);

                // WeightedPPrediction
                inProfile.PFrameWeightedPrediction = GetWeightp(inProfile, device);
                if (inProfile.PFrameWeightedPrediction != X264Settings.GetDefaultNumberOfWeightp(inProfile.Preset,
                                                                                                 inProfile.Tuning,
                                                                                                 inProfile.AVCProfile,
                                                                                                 inProfile.UseBluRayCompatibility))
                    sb.AppendFormat(AppSettings.CInfo, "--weightp {0:0} ", inProfile.PFrameWeightedPrediction);

                // Slicing
                inProfile.NumSlices = GetSlices(inProfile, device);
                if (inProfile.NumSlices != 0)
                    sb.AppendFormat(AppSettings.CInfo, "--slices {0:0} ", inProfile.NumSlices);

                if (!inProfile.CustomCommandLine.Contains("--slice-max-size "))
                    if (inProfile.MaxSliceSizeBytes != 0)
                        sb.AppendFormat(AppSettings.CInfo, "--slice-max-size {0:0} ", inProfile.MaxSliceSizeBytes);

                if (!inProfile.CustomCommandLine.Contains("--slice-max-mbs "))
                    if (inProfile.MaxSliceSizeBlocks != 0)
                        sb.AppendFormat(AppSettings.CInfo, "--slice-max-mbs {0:0} ", inProfile.MaxSliceSizeBlocks);

                #endregion

                #region rc tab

                if (!inProfile.CustomCommandLine.Contains("--qpmin"))
                    if (inProfile.QuantizerMin != 0)
                        sb.AppendFormat(AppSettings.CInfo, "--qpmin {0:0} ", inProfile.QuantizerMin);

                if (!inProfile.CustomCommandLine.Contains("--qpmax"))
                    if (inProfile.QuantizerMax != 69)
                        sb.AppendFormat(AppSettings.CInfo, "--qpmax {0:0} ", inProfile.QuantizerMax);

                if (!inProfile.CustomCommandLine.Contains("--qpstep"))
                    if (inProfile.QuantizerDelta != 4)
                        sb.AppendFormat(AppSettings.CInfo, "--qpstep {0:0} ", inProfile.QuantizerDelta);

                if (Math.Abs(inProfile.QuantizerRatioIP - 1.4F) > 0)
                {
                    display = true;
                    if (inProfile.Tuning == 3 && Math.Abs(inProfile.QuantizerRatioIP - 1.1F) <= 0)
                        display = false;

                    if (!inProfile.CustomCommandLine.Contains("--ipratio"))
                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--ipratio {0:0} ", inProfile.QuantizerRatioIP);
                }

                if (Math.Abs(inProfile.QuantizerRatioPB - 1.3F) > 0)
                {
                    display = true;
                    if (inProfile.Tuning == 3 && Math.Abs(inProfile.QuantizerRatioPB - 1.1F) <= 0)
                        display = false;

                    if (!inProfile.CustomCommandLine.Contains("--pbratio"))
                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--pbratio {0:0} ", inProfile.QuantizerRatioPB);
                }

                if (!inProfile.CustomCommandLine.Contains("--chroma-qp-offset"))
                    if (inProfile.ChromaQPOffset != 0)
                        sb.AppendFormat(AppSettings.CInfo, "--chroma-qp-offset {0:0} ", inProfile.ChromaQPOffset);

                if (inProfile.EncodingMode != 1) // doesn't apply to CQ mode
                {
                    inProfile.VBVBufSize = GetVBVBufsize(inProfile, device);
                    if (inProfile.VBVBufSize > 0)
                        sb.AppendFormat(AppSettings.CInfo, "--vbv-bufsize {0:0} ", inProfile.VBVBufSize);

                    inProfile.VBVMaxRate = GetVBVMaxrate(inProfile, device);
                    if (inProfile.VBVMaxRate > 0)
                        sb.AppendFormat(AppSettings.CInfo, "--vbv-maxrate {0:0} ", inProfile.VBVMaxRate);

                    if (!inProfile.CustomCommandLine.Contains("--vbv-init"))
                        if (Math.Abs(inProfile.VBVInitialBuffer - 0.9F) > 0)
                            sb.AppendFormat(AppSettings.CInfo, "--vbv-init {0:0.0} ", inProfile.VBVInitialBuffer);

                    if (!inProfile.CustomCommandLine.Contains("--ratetol"))
                        if (Math.Abs(inProfile.BitrateVariance - 1.0F) > 0)
                            sb.AppendFormat(AppSettings.CInfo, "--ratetol {0:0.0} ", inProfile.BitrateVariance);

                    if (!inProfile.CustomCommandLine.Contains("--qcomp"))
                    {
                        display = true;
                        if ((inProfile.Tuning == 3 && Math.Abs(inProfile.QuantizerCompression - 0.8F) <= 0) || (inProfile.Tuning != 3 && Math.Abs(inProfile.QuantizerCompression - 0.6F) <= 0))
                            display = false;
                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--qcomp {0:0.0} ", inProfile.QuantizerCompression);
                    }

                    if (inProfile.EncodingMode > 1) // applies only to twopass
                    {
                        if (!inProfile.CustomCommandLine.Contains("--cplxblur"))
                            if (inProfile.TempBlurFrameComplexity != 20)
                                sb.AppendFormat(AppSettings.CInfo, "--cplxblur {0:0} ", inProfile.TempBlurFrameComplexity);

                        if (!inProfile.CustomCommandLine.Contains("--qblur"))
                            if (Math.Abs(inProfile.TempBlurQuant - 0.5F) > 0)
                                sb.AppendFormat(AppSettings.CInfo, "--qblur {0:0.0} ", inProfile.TempBlurQuant);
                    }
                }

                // Dead Zones
                if (!inProfile.CustomCommandLine.Contains("--deadzone-inter"))
                {
                    display = true;
                    if ((inProfile.Tuning != 3 && inProfile.DeadZoneInter == 21 && inProfile.DeadZoneIntra == 11) ||
                        (inProfile.Tuning == 3 && inProfile.DeadZoneInter == 6 && inProfile.DeadZoneIntra == 6))
                        display = false;
                    if (display)
                        sb.AppendFormat(AppSettings.CInfo, "--deadzone-inter {0:0} ", inProfile.DeadZoneInter);
                }

                if (!inProfile.CustomCommandLine.Contains("--deadzone-intra"))
                {
                    display = true;
                    if ((inProfile.Tuning != 3 && inProfile.DeadZoneIntra == 11) || (inProfile.Tuning == 3 && inProfile.DeadZoneIntra == 6))
                        display = false;
                    if (display)
                        sb.AppendFormat(AppSettings.CInfo, "--deadzone-intra {0:0} ", inProfile.DeadZoneIntra);
                }

                // Disable Macroblok Tree
                if (!inProfile.UseMBTree)
                {
                    if (!inProfile.CustomCommandLine.Contains("--no-mbtree"))
                        if (inProfile.Preset > 0) // preset veryfast
                            sb.Append("--no-mbtree ");
                }
                else
                {
                    // RC Lookahead
                    if (!inProfile.CustomCommandLine.Contains("--rc-lookahead"))
                    {
                        display = false;
                        switch (inProfile.Preset)
                        {
                            case 0:
                            case 1: if (inProfile.NumFramesLookahead != 0) display = true; break;
                            case 2: if (inProfile.NumFramesLookahead != 10) display = true; break;
                            case 3: if (inProfile.NumFramesLookahead != 20) display = true; break;
                            case 4: if (inProfile.NumFramesLookahead != 30) display = true; break;
                            case 5: if (inProfile.NumFramesLookahead != 40) display = true; break;
                            case 6: if (inProfile.NumFramesLookahead != 50) display = true; break;
                            case 7:
                            case 8:
                            case 9: if (inProfile.NumFramesLookahead != 60) display = true; break;
                        }
                        if (display)
                            sb.AppendFormat("--rc-lookahead {0:0} ", inProfile.NumFramesLookahead);
                    }
                }

                // AQ-Mode
                if (inProfile.EncodingMode != 1)
                {
                    if (!inProfile.CustomCommandLine.Contains("--aq-mode"))
                    {
                        if (inProfile.AdaptiveQuantizersMode != X264Settings.GetDefaultAQMode(inProfile.Preset, inProfile.Tuning))
                            sb.AppendFormat("--aq-mode {0:0} ", inProfile.AdaptiveQuantizersMode);
                    }

                    if (inProfile.AdaptiveQuantizersMode > 0)
                    {
                        display = false;
                        switch (inProfile.Tuning)
                        {
                            case 2: if (Math.Abs(inProfile.AdaptiveQuantizersStrength - 0.6F) > 0) display = true; break;
                            case 3: if (Math.Abs(inProfile.AdaptiveQuantizersStrength - 0.5F) > 0) display = true; break;
                            case 7: if (Math.Abs(inProfile.AdaptiveQuantizersStrength - 1.3F) > 0) display = true; break;
                            default: if (Math.Abs(inProfile.AdaptiveQuantizersStrength - 1.0F) > 0) display = true; break;
                        }
                        if (!inProfile.CustomCommandLine.Contains("--aq-strength"))
                            if (display)
                                sb.AppendFormat(AppSettings.CInfo, "--aq-strength {0:0.0} ", inProfile.AdaptiveQuantizersStrength);
                    }
                }

                // custom matrices
                if (inProfile.AVCProfile > 1 && inProfile.QuantizerMatrix > 0)
                {
                    switch (inProfile.QuantizerMatrix)
                    {
                        case 1: if (!inProfile.CustomCommandLine.Contains("--cqm")) sb.Append("--cqm \"jvt\" "); break;
                    }
                }
                #endregion

                #region analysis tab

                // Disable Chroma Motion Estimation
                if (!inProfile.CustomCommandLine.Contains("--no-chroma-me"))
                    if (!inProfile.UseChromaMotionEstimation)
                        sb.Append("--no-chroma-me ");

                // Motion Estimation Range
                if (!inProfile.CustomCommandLine.Contains("--merange"))
                {
                    if ((inProfile.Preset <= 7 && inProfile.MotionEstimationRange != 16) ||
                        (inProfile.Preset >= 8 && inProfile.MotionEstimationRange != 24))
                        sb.AppendFormat("--merange {0:0} ", inProfile.MotionEstimationRange);
                }

                // ME Type
                if (!inProfile.CustomCommandLine.Contains("--me "))
                {
                    display = false;
                    switch (inProfile.Preset)
                    {
                        case 0:
                        case 1: if (inProfile.MotionEstimationAlgorithm != 0) display = true; break;
                        case 2:
                        case 3:
                        case 4:
                        case 5: if (inProfile.MotionEstimationAlgorithm != 1) display = true; break;
                        case 6:
                        case 7:
                        case 8: if (inProfile.MotionEstimationAlgorithm != 2) display = true; break;
                        case 9: if (inProfile.MotionEstimationAlgorithm != 4) display = true; break;
                    }

                    if (display)
                    {
                        switch (inProfile.MotionEstimationAlgorithm)
                        {
                            case 0: sb.Append("--me dia "); break;
                            case 1: sb.Append("--me hex "); break;
                            case 2: sb.Append("--me umh "); break;
                            case 3: sb.Append("--me esa "); break;
                            case 4: sb.Append("--me tesa "); break;
                        }
                    }

                }

                if (!inProfile.CustomCommandLine.Contains("--direct "))
                {
                    display = false;
                    if (inProfile.Preset > 5) // preset medium
                    {
                        if (inProfile.MVPredictionMod != 3)
                            display = true;
                    }
                    else if (inProfile.MVPredictionMod != 1)
                        display = true;

                    if (display)
                    {
                        switch (inProfile.MVPredictionMod)
                        {
                            case 0: sb.Append("--direct none "); break;
                            case 1: sb.Append("--direct spatial "); break;
                            case 2: sb.Append("--direct temporal "); break;
                            case 3: sb.Append("--direct auto "); break;
                        }
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--nr "))
                    if (inProfile.NoiseReduction > 0)
                        sb.AppendFormat("--nr {0:0} ", inProfile.NoiseReduction);

                // subpel refinement
                if (!inProfile.CustomCommandLine.Contains("--subme "))
                {
                    display = false;
                    switch (inProfile.Preset)
                    {
                        case 0: if (inProfile.SubPixelRefinement != 0) display = true; break;
                        case 1: if (inProfile.SubPixelRefinement != 1) display = true; break;
                        case 2: if (inProfile.SubPixelRefinement != 2) display = true; break;
                        case 3: if (inProfile.SubPixelRefinement != 4) display = true; break;
                        case 4: if (inProfile.SubPixelRefinement != 6) display = true; break;
                        case 5: if (inProfile.SubPixelRefinement != 7) display = true; break;
                        case 6: if (inProfile.SubPixelRefinement != 8) display = true; break;
                        case 7: if (inProfile.SubPixelRefinement != 9) display = true; break;
                        case 8: if (inProfile.SubPixelRefinement != 10) display = true; break;
                        case 9: if (inProfile.SubPixelRefinement != 11) display = true; break;
                    }
                    if (display)
                        sb.AppendFormat("--subme {0:0} ", inProfile.SubPixelRefinement);
                }

                // macroblock types
                if (!inProfile.CustomCommandLine.Contains("--partitions "))
                {
                    bool bExpectedP8X8Mv = true;
                    bool bExpectedB8X8Mv = true;
                    bool bExpectedI4X4Mv = true;
                    bool bExpectedI8X8Mv = true;
                    bool bExpectedP4X4Mv = true;

                    switch (inProfile.Preset)
                    {
                        case 0:
                            bExpectedP8X8Mv = false;
                            bExpectedB8X8Mv = false;
                            bExpectedI4X4Mv = false;
                            bExpectedI8X8Mv = false;
                            bExpectedP4X4Mv = false;
                            break;
                        case 1:
                            bExpectedP8X8Mv = false;
                            bExpectedB8X8Mv = false;
                            bExpectedP4X4Mv = false;
                            break;
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                            bExpectedP4X4Mv = false;
                            break;
                    }
                    if (inProfile.Tuning == 7 && bExpectedP8X8Mv)
                        bExpectedP4X4Mv = true;

                    if (inProfile.AVCProfile < 2)
                        bExpectedI8X8Mv = false;

                    if (bExpectedP8X8Mv != inProfile.MacroBlocksPartitionsP8X8 || bExpectedB8X8Mv != inProfile.MacroBlocksPartitionsB8X8
                        || bExpectedI4X4Mv != inProfile.MacroBlocksPartitionsI4X4 || bExpectedI8X8Mv != inProfile.MacroBlocksPartitionsI8X8
                        || bExpectedP4X4Mv != inProfile.MacroBlocksPartitionsP4X4)
                    {
                        if (inProfile.MacroBlocksPartitionsP8X8 ||
                            inProfile.MacroBlocksPartitionsB8X8 ||
                            inProfile.MacroBlocksPartitionsI4X4 ||
                            inProfile.MacroBlocksPartitionsI8X8 ||
                            inProfile.MacroBlocksPartitionsP4X4)
                        {
                            sb.Append("--partitions ");
                            if (inProfile.MacroBlocksPartitionsI4X4 &&
                                    inProfile.MacroBlocksPartitionsI8X8 &&
                                    inProfile.MacroBlocksPartitionsP4X4 &&
                                    inProfile.MacroBlocksPartitionsP8X8 &&
                                    inProfile.MacroBlocksPartitionsB8X8)
                                sb.Append("all ");
                            else
                            {
                                if (inProfile.MacroBlocksPartitionsP8X8) // default is checked
                                    sb.Append("p8x8,");
                                if (inProfile.MacroBlocksPartitionsB8X8) // default is checked
                                    sb.Append("b8x8,");
                                if (inProfile.MacroBlocksPartitionsI4X4) // default is checked
                                    sb.Append("i4x4,");
                                if (inProfile.MacroBlocksPartitionsP4X4) // default is unchecked
                                    sb.Append("p4x4,");
                                if (inProfile.MacroBlocksPartitionsI8X8) // default is checked
                                    sb.Append("i8x8");
                                if (sb.ToString().EndsWith(","))
                                    sb.Remove(sb.Length - 1, 1);
                            }

                            if (!sb.ToString().EndsWith(" "))
                                sb.Append(" ");
                        }
                        else
                            sb.Append("--partitions none ");
                    }
                }

                if (inProfile.AVCProfile > 1 && !inProfile.CustomCommandLine.Contains("--no-8x8dct"))
                    if (!inProfile.MacroBlocksPartitionsAdaptiveDCT)
                        if (inProfile.Preset > 0)
                            sb.Append("--no-8x8dct ");

                // Trellis
                if (!inProfile.CustomCommandLine.Contains("--trellis "))
                {
                    display = false;
                    switch (inProfile.Preset)
                    {
                        case 0:
                        case 1:
                        case 2: if (inProfile.Trellis != 0) display = true; break;
                        case 3:
                        case 4:
                        case 5:
                        case 6: if (inProfile.Trellis != 1) display = true; break;
                        case 7:
                        case 8:
                        case 9: if (inProfile.Trellis != 2) display = true; break;
                    }
                    if (display)
                        sb.AppendFormat("--trellis {0:0} ", inProfile.Trellis);
                }

                if (!inProfile.CustomCommandLine.Contains("--psy-rd "))
                {
                    if (inProfile.SubPixelRefinement > 5)
                    {
                        display = false;
                        switch (inProfile.Tuning)
                        {
                            case 1: if ((Math.Abs(inProfile.PsyRDStrength - 1.0F) > 0) || (Math.Abs(inProfile.PsyTrellisStrength - 0.15F) > 0)) display = true; break;
                            case 2: if ((Math.Abs(inProfile.PsyRDStrength - 0.4F) > 0) || (Math.Abs(inProfile.PsyTrellisStrength - 0.0F) > 0)) display = true; break;
                            case 3: if ((Math.Abs(inProfile.PsyRDStrength - 1.0F) > 0) || (Math.Abs(inProfile.PsyTrellisStrength - 0.25F) > 0)) display = true; break;
                            case 7: if ((Math.Abs(inProfile.PsyRDStrength - 1.0F) > 0) || (Math.Abs(inProfile.PsyTrellisStrength - 0.2F) > 0)) display = true; break;
                            default: if ((Math.Abs(inProfile.PsyRDStrength - 1.0F) > 0) || (Math.Abs(inProfile.PsyTrellisStrength - 0.0F) > 0)) display = true; break;
                        }

                        if (display)
                            sb.AppendFormat(AppSettings.CInfo, "--psy-rd {0:0.00}:{1:0.00} ", inProfile.PsyRDStrength, inProfile.PsyTrellisStrength);
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--no-mixed-refs"))
                    if (inProfile.UseNoMixedReferenceFrames)
                        if (inProfile.Preset >= 4) // preset fast
                            sb.Append("--no-mixed-refs ");

                if (!inProfile.CustomCommandLine.Contains("--no-dct-decimate"))
                    if (inProfile.UseNoDCTDecimation)
                        if (inProfile.Tuning != 3) // tune grain
                            sb.Append("--no-dct-decimate ");

                if (!inProfile.CustomCommandLine.Contains("--no-fast-pskip"))
                    if (inProfile.UseNoFastPSkip)
                        if (inProfile.Preset != 9) // preset placebo
                            sb.Append("--no-fast-pskip ");

                if (!inProfile.CustomCommandLine.Contains("--no-psy"))
                    if (inProfile.UseNoPsychovisualEnhancements && (inProfile.Tuning != 5 && inProfile.Tuning != 6))
                        sb.Append("--no-psy ");

                inProfile.UseAccessUnitDelimiters = GetAud(inProfile, device);
                if (inProfile.UseAccessUnitDelimiters && !inProfile.UseBluRayCompatibility)
                    sb.Append("--aud ");

                inProfile.HRDInfo = GetNalHrd(inProfile, device);
                switch (inProfile.HRDInfo)
                {
                    case 1: if (!inProfile.UseBluRayCompatibility) sb.Append("--nal-hrd vbr "); break;
                    case 2: sb.Append("--nal-hrd cbr "); break;
                }

                if (!inProfile.CustomCommandLine.Contains("--non-deterministic"))
                    if (inProfile.UseNonDeterministic)
                        sb.Append("--non-deterministic ");
                #endregion

                #region misc tab

                if (!inProfile.CustomCommandLine.Contains("--psnr"))
                    if (inProfile.UsePSNRCalculation)
                        sb.Append("--psnr ");

                if (!inProfile.CustomCommandLine.Contains("--ssim"))
                    if (inProfile.UseSSIMCalculation)
                        sb.Append("--ssim ");

                if (!inProfile.CustomCommandLine.Contains("--range "))
                    switch (inProfile.VUIRange)
                    {
                        case 1:
                            sb.AppendFormat("--range tv ");
                            break;
                        case 2:
                            sb.Append("--range pc ");
                            break;
                    }

                #endregion

                #region input / ouput / custom

                string customSarValue = string.Empty;

                Dar? d = new Dar((ulong)hRes, (ulong)vRes);

                if (inProfile.UseAutoSelectSAR)
                {
                    int tempValue = GetSar(inProfile, d, hRes, vRes, out customSarValue, String.Empty);
                    inProfile.ForceSAR = tempValue;
                }

                if (inProfile.UseAutoSelectColorSettings)
                {
                    inProfile.ColorPrimaries = GetColorprim(inProfile, format);

                    inProfile.Transfer = GetTransfer(inProfile, format);

                    inProfile.ColorMatrix = GetColorMatrix(inProfile, format);
                }

                if (device.BluRay)
                {
                    if (inProfile.InterlaceMode < 2)
                        inProfile.InterlaceMode = GetInterlacedMode(format);

                    inProfile.UseFakeInterlaced = GetFakeInterlaced(inProfile, format, fpsN, fpsD);

                    inProfile.UseForcePicStruct = GetPicStruct(inProfile, format);

                    inProfile.Pulldown = GetPulldown(inProfile, format, fpsN, fpsD);
                }
                else
                {
                    if (inProfile.InterlaceMode == 0)
                        inProfile.InterlaceMode = GetInterlacedMode(format);

                    if (inProfile.Pulldown == 0)
                        inProfile.Pulldown = GetPulldown(inProfile, format, fpsN, fpsD);
                }

                if (!inProfile.CustomCommandLine.Contains("--bff") &&
                    !inProfile.CustomCommandLine.Contains("--tff"))
                {
                    switch (inProfile.InterlaceMode)
                    {
                        case 2: sb.Append("--bff "); break;
                        case 3: sb.Append("--tff "); break;
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--fake-interlaced"))
                {
                    if (inProfile.UseFakeInterlaced && inProfile.InterlaceMode == 1)
                        sb.Append("--fake-interlaced ");
                }

                if (!inProfile.CustomCommandLine.Contains("--pic-struct"))
                {
                    if (inProfile.UseForcePicStruct && inProfile.InterlaceMode == 1 && inProfile.Pulldown == 0)
                        sb.Append("--pic-struct ");
                }

                if (!inProfile.CustomCommandLine.Contains("--colorprim"))
                {
                    switch (inProfile.ColorPrimaries)
                    {
                        case 0: break;
                        case 1: sb.Append("--colorprim bt709 "); break;
                        case 2: sb.Append("--colorprim bt470m "); break;
                        case 3: sb.Append("--colorprim bt470bg "); break;
                        case 4: sb.Append("--colorprim smpte170m "); break;
                        case 5: sb.Append("--colorprim smpte240m "); break;
                        case 6: sb.Append("--colorprim film "); break;
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--transfer"))
                {
                    switch (inProfile.Transfer)
                    {
                        case 0: break;
                        case 1: sb.Append("--transfer bt709 "); break;
                        case 2: sb.Append("--transfer bt470m "); break;
                        case 3: sb.Append("--transfer bt470bg "); break;
                        case 4: sb.Append("--transfer linear "); break;
                        case 5: sb.Append("--transfer log100 "); break;
                        case 6: sb.Append("--transfer log316 "); break;
                        case 7: sb.Append("--transfer smpte170m "); break;
                        case 8: sb.Append("--transfer smpte240m "); break;
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--colormatrix"))
                {
                    switch (inProfile.ColorMatrix)
                    {
                        case 0: break;
                        case 1: sb.Append("--colormatrix bt709 "); break;
                        case 2: sb.Append("--colormatrix fcc "); break;
                        case 3: sb.Append("--colormatrix bt470bg "); break;
                        case 4: sb.Append("--colormatrix smpte170m "); break;
                        case 5: sb.Append("--colormatrix smpte240m "); break;
                        case 6: sb.Append("--colormatrix GBR "); break;
                        case 7: sb.Append("--colormatrix YCgCo "); break;
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--pulldown"))
                {
                    switch (inProfile.Pulldown)
                    {
                        case 0: break;
                        case 1: break;
                        case 2: sb.Append("--pulldown 22 "); break;
                        case 3: sb.Append("--pulldown 32 "); break;
                        case 4: sb.Append("--pulldown 64 "); break;
                        case 5: sb.Append("--pulldown double "); break;
                        case 6: sb.Append("--pulldown triple "); break;
                        case 7: sb.Append("--pulldown euro "); break;
                    }
                }

                if (!String.IsNullOrEmpty(inProfile.CustomCommandLine)) // add custom encoder options
                    sb.Append(Regex.Replace(inProfile.CustomCommandLine, @"\r\n?|\n", string.Empty).Trim() + " ");

                if (!inProfile.CustomCommandLine.Contains("--sar"))
                {
                    switch (inProfile.ForceSAR)
                    {
                        case 0:
                            {
                                if (!String.IsNullOrEmpty(customSarValue))
                                    sb.Append("--sar " + customSarValue + " ");
                                break;
                            }
                        case 1: sb.Append("--sar 1:1 "); break;
                        case 2: sb.Append("--sar 4:3 "); break;
                        case 3: sb.Append("--sar 8:9 "); break;
                        case 4: sb.Append("--sar 10:11 "); break;
                        case 5: sb.Append("--sar 12:11 "); break;
                        case 6: sb.Append("--sar 16:11 "); break;
                        case 7: sb.Append("--sar 32:27 "); break;
                        case 8: sb.Append("--sar 40:33 "); break;
                        case 9: sb.Append("--sar 64:45 "); break;
                    }
                }

                if (!inProfile.CustomCommandLine.Contains("--frame-packing"))
                {
                    if (stereo != StereoEncoding.None)
                        sb.Append("--frame-packing 3 ");
                }

                //add the rest of the commandline regarding the output
                if ((inProfile.EncodingMode == 2 || inProfile.EncodingMode == 3) && (tempPass == 1))
                    sb.Append("--output NUL ");
                else if (!String.IsNullOrEmpty(outFile))
                    sb.AppendFormat("--output \"{0}\" ", outFile);

                if (!String.IsNullOrEmpty(inFile))
                {
                    if (String.CompareOrdinal(inFile, "-") == 0)
                        sb.AppendFormat("--demuxer y4m - ");
                    else
                        sb.AppendFormat("\"{0}\" ", inFile);
                }

                #endregion
            }
            return sb.ToString();
        }
        /// <summary>
        /// Generates AviSynth script used for video encoding
        /// </summary>
        /// <param name="videoInfo">All video properties</param>
        /// <param name="changeFps">Defines whether framerate should be changed</param>
        /// <param name="targetFps">Sets target framerate</param>
        /// <param name="resizeTo">Sets target video resolution</param>
        /// <param name="stereoEncoding">Defines, which stereo encoding mode should be used</param>
        /// <param name="stereoVideoInfo">Sets all parameters for stereo encoding</param>
        /// <param name="isDvdResolution">Defines whether target resolution is used for DVD encoding</param>
        /// <param name="subtitleFile">Sets subtitle file for hardcoding into video</param>
        /// <param name="subtitleOnlyForced">Defines whether only forced captions should be hardcoded</param>
        /// <returns>Path to AviSynth script</returns>
        public static string Generate(VideoInfo videoInfo, bool changeFps, float targetFps, Size resizeTo,
                                      StereoEncoding stereoEncoding, StereoVideoInfo stereoVideoInfo, bool isDvdResolution, string subtitleFile, bool subtitleOnlyForced)
        {
            StringBuilder sb = new StringBuilder();

            bool mtUseful = (videoInfo.Interlaced && AppSettings.UseHQDeinterlace) || changeFps;

            bool useStereo = stereoEncoding != StereoEncoding.None && stereoVideoInfo.RightStreamId > -1;

            // support for multithreaded AviSynth
            if (AppSettings.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(2,0)");
                sb.AppendLine("SetMemoryMax(512)");
            }

            //loading plugins
            sb.AppendLine(ImportFFMPEGSource());  // ffms2

            if (changeFps || (videoInfo.Interlaced && AppSettings.UseHQDeinterlace))
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "mvtools2.dll")));

            if (videoInfo.Interlaced && AppSettings.UseHQDeinterlace)
            {
                sb.AppendLine(AppSettings.LastAviSynthVer.StartsWith("2.5")
                                  ? string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                                  Path.Combine(AppSettings.AppPath, "AvsPlugins", "mt_masktools-25.dll"))
                                  : string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                                  Path.Combine(AppSettings.AppPath, "AvsPlugins", "mt_masktools-26.dll")));

                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "nnedi3.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "RemoveGrainSSE2.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "RepairSSE2.dll")));
                sb.AppendLine(string.Format(AppSettings.CInfo, "Import(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "QTGMC-3.32.avsi")));
            }
            else if (videoInfo.Interlaced)
            {
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "Decomb.dll")));
            }

            if (useStereo)
                sb.AppendLine(string.Format(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                            Path.Combine(AppSettings.AppPath, "AvsPlugins", "H264StereoSource.dll")));

            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                    case "sup":
                        sb.AppendFormat(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                        Path.Combine(AppSettings.AppPath, "AvsPlugins", "SupTitle.dll"));
                        break;
                    case "ass":
                    case "ssa":
                    case "srt":
                        sb.AppendFormat(AppSettings.CInfo, "LoadPlugin(\"{0:s}\")",
                                        Path.Combine(AppSettings.AppPath, "AvsPlugins", "VSFilter.dll"));
                        break;
                }
                sb.AppendLine();
            }

            //generate rest of the script

            // calculate framerate numerator & denominator
            if (videoInfo.FPS <= 0)
            {
                MediaInfoContainer mi = new MediaInfoContainer();
                try
                {
                     mi = Processing.GetMediaInfo(videoInfo.TempFile);
                }
                catch (TimeoutException ex)
                {
                    Log.Error(ex);
                    mi = new MediaInfoContainer();
                }
                finally
                {
                    if (mi.Video.Count > 0)
                    {
                        videoInfo.FPS = mi.Video[0].FrameRate;
                        Processing.GetFPSNumDenom(videoInfo.FPS, out videoInfo.FrameRateEnumerator,
                                                  out videoInfo.FrameRateDenominator);

                        if (videoInfo.FrameRateEnumerator == 0)
                        {
                            videoInfo.FrameRateEnumerator = (int)Math.Round(videoInfo.FPS) * 1000;
                            videoInfo.FrameRateDenominator =
                                (int)(Math.Round(Math.Ceiling(videoInfo.FPS) - Math.Floor(videoInfo.FPS)) + 1000);
                        }
                    }
                }

            }

            if (videoInfo.FrameRateEnumerator > 0 && videoInfo.FrameRateDenominator > 0)
                sb.AppendLine(string.Format(AppSettings.CInfo,
                                            "FFVideoSource(\"{0:s}\",fpsnum={1:0},fpsden={2:0},threads=1)",
                                            videoInfo.TempFile, videoInfo.FrameRateEnumerator,
                                            videoInfo.FrameRateDenominator));
            else
                sb.AppendLine(string.Format(AppSettings.CInfo, "FFVideoSource(\"{0:s}\",threads=1)", videoInfo.TempFile));

            string stereoVar = string.Empty;

            if (useStereo)
            {
                string configFile = GenerateStereoSourceConfig(stereoVideoInfo);
                sb.AppendLine(string.Format(AppSettings.CInfo, "VideoRight = H264StereoSource(\"{0:s}\",{1:g})",
                                            configFile, videoInfo.FrameCount - 50));
                StereoConfigFile = configFile;
                stereoVar = "VideoRight";
            }

            // deinterlace video source
            if (videoInfo.Interlaced)
            {
                if (AppSettings.UseHQDeinterlace)
                    sb.AppendLine("QTGMC(Preset=\"Slower\")");
                else
                {
                    sb.AppendLine("ConvertToYUY2(interlaced=true)");
                    sb.AppendLine("Telecide(post=4)");
                    sb.AppendLine("Crop(4, 0, -4, 0)");
                    sb.AppendLine("AddBorders(4, 0, 4, 0)");
                    sb.AppendLine("ConvertToYV12()");
                }
            }

            // hardcode subtitles
            if (!string.IsNullOrEmpty(subtitleFile) && File.Exists(subtitleFile))
            {
                switch (Path.GetExtension(subtitleFile))
                {
                    case "sup":
                        sb.AppendFormat(AppSettings.CInfo, "SupTitle(\"{0}\", forcedOnly={1})", subtitleFile,
                                                        subtitleOnlyForced ? "true" : "false");
                        break;
                    case "ass":
                    case "ssa":
                    case "srt":
                        sb.AppendFormat(AppSettings.CInfo, "TextSub(\"{0}\")", subtitleFile);
                        break;
                }

                sb.AppendLine();
            }

            // video cropping
            if (!videoInfo.CropRect.IsEmpty)
            {
                int temp;

                Math.DivRem(videoInfo.CropRect.X, 2, out temp);
                videoInfo.CropRect.X += temp;
                Math.DivRem(videoInfo.CropRect.Y, 2, out temp);
                videoInfo.CropRect.Y += temp;
                Math.DivRem(videoInfo.CropRect.Width, 2, out temp);
                videoInfo.CropRect.Width += temp;
                Math.DivRem(videoInfo.CropRect.Height, 2, out temp);
                videoInfo.CropRect.Height += temp;

                videoInfo.Height = videoInfo.CropRect.Height;
                videoInfo.Width = videoInfo.CropRect.Width;

                if ((videoInfo.CropRect.X > 0) || (videoInfo.CropRect.Y > 0) || (videoInfo.CropRect.Width < videoInfo.Width) ||
                    (videoInfo.CropRect.Height < videoInfo.Height))
                {
                    sb.AppendLine(string.Format(AppSettings.CInfo, "Crop({0:g},{1:g},{2:g},{3:g})",
                                                videoInfo.CropRect.Left,
                                                videoInfo.CropRect.Top,
                                                videoInfo.CropRect.Width,
                                                videoInfo.CropRect.Height));
                    if (useStereo)
                    {
                        sb.AppendLine(string.Format(AppSettings.CInfo,
                                                    "CroppedVideoRight = Crop(VideoRight,{0:g},{1:g},{2:g},{3:g})",
                                                    videoInfo.CropRect.Left,
                                                    videoInfo.CropRect.Top,
                                                    videoInfo.CropRect.Width,
                                                    videoInfo.CropRect.Height));
                        stereoVar = "CroppedVideoRight";
                    }
                }
            }

            // Side-By-Side stereo encoding
            if (!string.IsNullOrEmpty(stereoVar))
            {
                switch(stereoEncoding)
                {
                    case StereoEncoding.FullSideBySideLeft:
                    case StereoEncoding.HalfSideBySideLeft:
                        sb.AppendLine(string.Format("StackHorizontal(last,{0})", stereoVar));
                        break;
                    case StereoEncoding.FullSideBySideRight:
                    case StereoEncoding.HalfSideBySideRight:
                        sb.AppendLine(string.Format("StackHorizontal({0},last)", stereoVar));
                        break;
                }
                sb.AppendLine("ConvertToYV12()");
            }

            int calculatedHeight = videoInfo.Height;
            int calculatedWidth = videoInfo.Width;
            int borderRight = 0;
            int borderLeft = 0;
            int borderBottom = 0;
            int borderTop = 0;
            bool addBorders = false;

            // video resizing
            if (!resizeTo.IsEmpty && (resizeTo.Height != videoInfo.Height || resizeTo.Width != videoInfo.Width))
            {
                // aspect ratios

                float toAr = (float) Math.Round(resizeTo.Width / (float)resizeTo.Height, 3);

                calculatedWidth = resizeTo.Width;

                float mod = 1f;

                if (videoInfo.AspectRatio > toAr) // source aspectratio higher than target aspectratio
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        if (calculatedHeight > resizeTo.Height)
                            calculatedHeight = resizeTo.Height;
                        calculatedWidth = 720;
                    }
                    else
                    {
                        calculatedWidth = resizeTo.Width;
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else if (Math.Abs(videoInfo.AspectRatio - toAr) <= 0)  // source and target aspectratio equals
                {
                    if (isDvdResolution)
                    {
                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        calculatedWidth = 720;
                        if (calculatedHeight > resizeTo.Height)
                            calculatedHeight = resizeTo.Height;
                    }
                    else
                    {
                        calculatedWidth = resizeTo.Width;
                        calculatedHeight = (int) (calculatedWidth/toAr);
                    }

                    int temp;

                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (calculatedHeight != resizeTo.Height)
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
                else
                {
                    if (videoInfo.AspectRatio > 1.4f && isDvdResolution)  // source aspectratio not 4:3, encoding for dvd resolution
                    {
                        mod = 720f/resizeTo.Width;

                        calculatedHeight = (int)(calculatedWidth / videoInfo.AspectRatio);
                        if (calculatedHeight > resizeTo.Height)
                        {
                            calculatedHeight = resizeTo.Height;
                            calculatedWidth = (int)(calculatedHeight * videoInfo.AspectRatio * mod);
                        }
                        else
                            calculatedWidth = 720;
                    }
                    else if (isDvdResolution)
                    {
                        calculatedHeight = resizeTo.Height;
                        calculatedWidth = (int) (calculatedHeight*videoInfo.AspectRatio);
                    }
                    else
                        calculatedHeight = resizeTo.Height;

                    int temp;
                    Math.DivRem(calculatedWidth, 2, out temp);
                    calculatedWidth += temp;
                    Math.DivRem(calculatedHeight, 2, out temp);
                    calculatedHeight += temp;

                    if (Math.Abs(toAr - 1.778f) <= 0)     // aspectratio 16:9
                    {
                        addBorders = true;
                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;

                        int borderWidth = (int) ((resizeTo.Width*mod) - calculatedWidth);
                        borderLeft = borderWidth/2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;
                    }
                    else if (calculatedWidth != resizeTo.Width)
                    {
                        addBorders = true;
                        int borderWidth = resizeTo.Width - calculatedWidth;
                        borderLeft = borderWidth/2;
                        Math.DivRem(borderLeft, 2, out temp);
                        borderLeft += temp;
                        borderRight = borderWidth - borderLeft;

                        int borderHeight = resizeTo.Height - calculatedHeight;
                        borderTop = borderHeight/2;
                        Math.DivRem(borderTop, 2, out temp);
                        borderTop += temp;
                        borderBottom = borderHeight - borderTop;
                    }
                }
            }

            // apply resize filter
            if (calculatedHeight != videoInfo.Height || calculatedWidth != videoInfo.Width ||
                (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                 stereoEncoding == StereoEncoding.HalfSideBySideRight
                && useStereo))
            {
                if (calculatedHeight < videoInfo.Height || calculatedWidth < videoInfo.Width ||
                    (stereoEncoding == StereoEncoding.HalfSideBySideLeft ||
                     stereoEncoding == StereoEncoding.HalfSideBySideRight
                     && useStereo))
                    sb.AppendLine(string.Format(AppSettings.CInfo, "BicubicResize({0:g},{1:g})",
                                                calculatedWidth,
                                                calculatedHeight));
                else
                    sb.AppendLine(string.Format(AppSettings.CInfo, "Lanczos4Resize({0:g},{1:g})",
                                                calculatedWidth,
                                                calculatedHeight));
            }

            // add borders if needed
            if (addBorders && (borderLeft > 0 || borderRight > 0 || borderTop > 0 || borderBottom > 0))
                sb.AppendLine(string.Format(AppSettings.CInfo, "AddBorders({0:g},{1:g},{2:g},{3:g})",
                                            borderLeft,
                                            borderTop,
                                            borderRight,
                                            borderBottom));

            // change framerate
            if (changeFps)
            {
                int fpsnum;
                int fpsden;

                // get framerate numerator & denominator for target framerate
                Processing.GetFPSNumDenom(targetFps, out fpsnum, out fpsden);

                // source is 23.976 or 24 fps
                if (videoInfo.FrameRateEnumerator == 24000 && (videoInfo.FrameRateDenominator == 1001 || videoInfo.FrameRateDenominator == 1000))
                {
                    if (fpsnum == 30000 && fpsden == 1001)
                    {
                        // 3:2 pulldown / telecine
                        sb.AppendLine("AssumeFrameBased()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        sb.AppendLine("Weave()");
                    }
                    else if (fpsnum == 25000 && fpsden == 1000)
                    {
                        // convert to 25 fps
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine("ConvertFPS(50)");
                        sb.AppendLine("AssumeTFF()");
                        sb.AppendLine("SeparateFields()");
                        sb.AppendLine("SelectEvery(4,0,3)");
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // source is 30fps
                else if (videoInfo.FrameRateEnumerator == 30000)
                {
                    sb.AppendLine("ConvertToYUY2()");
                    sb.AppendLine("DoubleWeave()");
                    sb.AppendLine(string.Format(AppSettings.CInfo, "ConvertFPS({0:0.000})", targetFps*2));
                    sb.AppendLine("SelectEven()");
                    sb.AppendLine("ConvertToYV12()");
                }
                // source is 25fps
                else if (videoInfo.FrameRateEnumerator == 25000 && videoInfo.FrameRateDenominator == 1000)
                {
                    if ((fpsnum == 30000 || fpsnum == 24000) && fpsden == 1001)
                    {
                        sb.AppendLine("ConvertToYUY2()");
                        sb.AppendLine(string.Format(AppSettings.CInfo, "ConvertFPS({0:0.000}*2)", 23.976));
                        if (fpsnum == 30000)
                        {
                            sb.AppendLine("AssumeFrameBased()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEvery(8, 0, 1, 2, 3, 2, 5, 4, 7, 6, 7)");
                        }
                        else
                        {
                            sb.AppendLine("AssumeTFF()");
                            sb.AppendLine("SeparateFields()");
                            sb.AppendLine("SelectEven()");
                        }
                        sb.AppendLine("Weave()");
                        sb.AppendLine("ConvertToYV12()");
                    }
                }
                // every other framerate
                else
                {
                    // very slow framerate interpolation
                    sb.AppendLine("super = MSuper(pel=2)");
                    sb.AppendLine("backward_vec = MAnalyse(super, overlap=4, isb = true, search=3)");
                    sb.AppendLine("forward_vec = MAnalyse(super, overlap=4, isb = false, search=3)");
                    sb.AppendFormat("MFlowFps(super, backward_vec, forward_vec, num={0:0}, den={1:0})", fpsnum,
                                    fpsden);
                }

                sb.AppendLine();
            }

            // multithreaded avisynth
            if (AppSettings.UseAviSynthMT && mtUseful)
            {
                sb.AppendLine("SetMTMode(1)");
                sb.AppendLine("GetMTMode(false) > 0 ? distributor() : last");
            }

            return WriteScript(sb.ToString());
        }