Imports Microsoft.Win32
Imports System.Runtime.Serialization
Imports System.Reflection
Imports System.Text.RegularExpressions
Imports System.Text

Imports Stax
Imports Stax.UI
Imports Stax.AppFramework

<Serializable()> _
Public MustInherit Class VideoEncoder
    Inherits Profile
    Implements IComparable(Of VideoEncoder)

    Public MustOverride Sub Encode()
    Public MustOverride Function GetMenu() As List(Of OptionListBoxItem)

    Public Sub New(ByVal name As String, ByVal typeName As String)
        MyBase.New(name, typeName)
        CanEditValue = True
    End Sub

    Private OutputPathValue As String

    Public Overridable ReadOnly Property OutputPath() As String
        Get
            If TypeOf Muxer Is EncoderMuxer OrElse TypeOf Muxer Is NullMuxer Then
                Return p.TargetFile
            Else
                Return Filepath.GetDir(p.SourceFile) + p.Name + "_EncoderOutput" + GetExtension()
            End If
        End Get
    End Property

    Private PassesValue As Integer

    Public Overridable Property Passes() As Integer
        Get
            Return PassesValue
        End Get
        Set(ByVal Value As Integer)
            PassesValue = Value
        End Set
    End Property

    Private QualityModeValue As Boolean

    Public Overridable Property QualityMode() As Boolean
        Get
            Return QualityModeValue
        End Get
        Set(ByVal Value As Boolean)
            QualityModeValue = Value
        End Set
    End Property

    Private MuxerValue As Muxer

    Public Property Muxer() As Muxer
        Get
            Return MuxerValue
        End Get
        Set(ByVal Value As Muxer)
            MuxerValue = Value
        End Set
    End Property

    Public Overrides ReadOnly Property EditControl() As Control
        Get
            If EditControlValue Is Nothing Then
                Dim olb As New OptionListBox
                olb.Dock = DockStyle.Fill
                olb.Items.AddRange(GetMenu.ToArray)
                EditControlValue = olb
            End If

            Return EditControlValue
        End Get
    End Property

    Protected IsCompCheckEnabledValue As Boolean

    Public ReadOnly Property IsCompCheckEnabled() As Boolean
        Get
            Return IsCompCheckEnabledValue AndAlso Not QualityMode
        End Get
    End Property

    Private AutoCompCheckValueValue As Integer = 70

    Public Property AutoCompCheckValue() As Integer
        Get
            Return AutoCompCheckValueValue
        End Get
        Set(ByVal Value As Integer)
            AutoCompCheckValueValue = Value
        End Set
    End Property

    Private OutputStreamTypeValue As StreamType

    Public Overridable Property OutputStreamType() As StreamType
        Get
            Return OutputStreamTypeValue
        End Get
        Set(ByVal value As StreamType)
            OutputStreamTypeValue = value
        End Set
    End Property

    Protected Sub OnAfterCompCheck()
        If p.CompCheckAction = CompCheckAction.AdjustFileSize Then
            g.MainForm.tbSize.Text = g.GetAutoSize(AutoCompCheckValue).ToString
        ElseIf p.CompCheckAction = CompCheckAction.AdjustImageSize Then
            AutoSetImageSize()
        End If
    End Sub

    Public Sub AutoSetImageSize()
        If p.VideoEncoder.AutoCompCheckValue > 0 AndAlso Calc.GetPercent <> 0 Then
            p.TargetWidth = Calc.FixMod(CInt((p.SourceHeight - p.CropTop - p.CropBottom) * Calc.GetAR()), 16)

            If p.TargetWidth > s.ResizeSliderMax.Value Then
                p.TargetWidth = s.ResizeSliderMax.Value
            End If

            p.TargetHeight = Calc.FixMod(CInt(p.TargetWidth / Calc.GetAR()), 16)

            While Calc.GetPercent < p.VideoEncoder.AutoCompCheckValue
                If p.TargetWidth - 16 >= s.ResizeSliderMin.Value Then
                    p.TargetWidth -= 16
                    p.TargetHeight = Calc.FixMod(CInt(p.TargetWidth / Calc.GetAR()), 16)
                Else
                    Exit While
                End If
            End While

            g.MainForm.tbTargetWidth.Text = p.TargetWidth.ToString
            g.MainForm.tbTargetHeight.Text = p.TargetHeight.ToString
        End If
    End Sub

    Public Overrides Sub Clean()
        Muxer.Clean()
    End Sub

    Public Overridable Function GetExtension() As String
        Return StreamTypeUtils.GetExtension(OutputStreamType)
    End Function

    Protected Sub OnStateChange()
        g.MainForm.UpdateEncoderStateRelatedControls()
        g.MainForm.Assistant()

        Dim olb As OptionListBox = DirectCast(EditControl, OptionListBox)
        olb.Items.Clear()
        olb.Items.AddRange(GetMenu.ToArray)
    End Sub

    Public Enum Modes
        First = 1
        Second = 2
        CompCheck = 4
    End Enum

    Protected Sub OpenMuxerConfigDialog()
        Muxer.Edit()
        g.MainForm.tbSize_TextChanged(Nothing, Nothing)
        g.MainForm.Assistant()
    End Sub

    Public Function OpenMuxerProfilesDialog() As DialogResult
        Using f As New ProfilesForm("Muxer Profiles", s.MuxerProfiles, AddressOf LoadMuxer, AddressOf GetMuxerProfile)
            Return f.ShowDialog()
        End Using
    End Function

    Public Sub LoadMuxer(ByVal profile As Profile)
        Muxer = DirectCast(ObjectHelp.GetCopy(profile), Muxer)
        Muxer.Init()
        g.MainForm.tbTargetPath.Text = Filepath.GetChangeExt(p.TargetFile, Muxer.GetExtension)
        g.MainForm.RecalcBitrate()
        g.MainForm.Assistant()
    End Sub

    Private Function GetMuxerProfile() As Profile
        Dim sb As New SelectionBox(Of Muxer)

        sb.Title = "New Profile"
        sb.Text = Strings.AddProfile

        sb.AddItem("Current Project", Muxer)

        For Each i As Muxer In StaxRip.Muxer.GetDefaults(True)
            sb.AddItem(i)
        Next

        If sb.Show = DialogResult.OK Then
            Return sb.SelecteItem
        End If

        Return Nothing
    End Function

    Public Shared Function GetDefaults() As List(Of VideoEncoder)
        Dim ret As New List(Of VideoEncoder)

        Dim xvidQuality As New XviDVirtualDubEncoder
        xvidQuality.Name = "XviD - Constant Quality"
        xvidQuality.Passes = 1
        xvidQuality.QualityMode = True
        xvidQuality.SetQualityModeRegDefaults()
        ret.Add(xvidQuality)

        Dim xvidTwoPass As New XviDVirtualDubEncoder
        xvidTwoPass.Name = "XviD - Exact File Size"
        xvidTwoPass.Passes = 2
        xvidTwoPass.QualityMode = False
        xvidTwoPass.SetTwoPassRegDefaults()
        xvidTwoPass.SetCompCheckRegDefaults()
        ret.Add(xvidTwoPass)

        Dim divxQuality As New DivXVirtualDubEncoder
        divxQuality.Name = "DivX - Constant Quality"
        divxQuality.QualityMode = True
        divxQuality.Passes = 1
        divxQuality.Verify()
        ret.Add(divxQuality)

        Dim divxTwoPass As New DivXVirtualDubEncoder
        divxTwoPass.Name = "DivX - Exact File Size"
        ret.Add(divxTwoPass)

        Dim _1PGoodquality As New x264Encoder()
        _1PGoodquality.Name = "x264 - 1P-Goodquality"
        _1PGoodquality.Params.BFrames.Value = 3
        _1PGoodquality.Params.BFramesPyramid.Value = True
        _1PGoodquality.Params.BFramesWeightedPrediction.Value = True
        _1PGoodquality.Params.ReferenceFrames.Value = 3
        _1PGoodquality.Params.DeblockAlpha.Value = 0
        _1PGoodquality.Params.DeblockBeta.Value = 0
        _1PGoodquality.Params.Mode.Value = 0
        _1PGoodquality.Params.AdaptiveDCT.Value = True
        _1PGoodquality.Params.I8x8.Value = True
        _1PGoodquality.Params.Trellis.Value = 1
        _1PGoodquality.Params.BFramesRDO.Value = True
        _1PGoodquality.Params.AddAll.Value = "--bime"
        ret.Add(_1PGoodquality)

        Dim _1PIntermediate As New x264Encoder()
        _1PIntermediate.Name = "x264 - 1P-Intermediate"
        _1PIntermediate.Params.BFrames.Value = 3
        _1PIntermediate.Params.BFramesWeightedPrediction.Value = True
        _1PIntermediate.Params.ReferenceFrames.Value = 1
        _1PIntermediate.Params.DeblockAlpha.Value = 0
        _1PIntermediate.Params.DeblockBeta.Value = 0
        _1PIntermediate.Params.Mode.Value = 0
        _1PIntermediate.Params.SubME.Value = 5
        ret.Add(_1PIntermediate)

        Dim _1PMaxspeed As New x264Encoder()
        _1PMaxspeed.Name = "x264 - 1P-Maxspeed"
        _1PMaxspeed.Params.BFrames.Value = 0
        _1PMaxspeed.Params.BFramesAdaptive.Value = False
        _1PMaxspeed.Params.CABAC.Value = False
        _1PMaxspeed.Params.ReferenceFrames.Value = 1
        _1PMaxspeed.Params.LoopFilter.Value = False
        _1PMaxspeed.Params.DeblockAlpha.Value = 0
        _1PMaxspeed.Params.DeblockBeta.Value = 0
        _1PMaxspeed.Params.Mode.Value = 0
        _1PMaxspeed.Params.SubME.Value = 1
        _1PMaxspeed.Params.MEMethod.Value = 0
        _1PMaxspeed.Params.AddAll.Value = "--no-chroma-me"
        ret.Add(_1PMaxspeed)

        Dim AEGoodquality As New x264Encoder()
        AEGoodquality.Name = "x264 - AE-Goodquality"
        AEGoodquality.Params.BFrames.Value = 3
        AEGoodquality.Params.BFramesPyramid.Value = True
        AEGoodquality.Params.BFramesWeightedPrediction.Value = True
        AEGoodquality.Params.ReferenceFrames.Value = 10
        AEGoodquality.Params.DeblockAlpha.Value = 1
        AEGoodquality.Params.DeblockBeta.Value = 1
        AEGoodquality.Params.Mode.Value = 3
        AEGoodquality.Params.AdaptiveDCT.Value = True
        AEGoodquality.Params.I8x8.Value = True
        AEGoodquality.Params.MixedRefs.Value = True
        AEGoodquality.Params.Trellis.Value = 1
        AEGoodquality.Params.MEMethod.Value = 2
        AEGoodquality.Params.BFramesRDO.Value = True
        AEGoodquality.Params.AddAll.Value = "--bime"
        ret.Add(AEGoodquality)

        Dim AEMaxquality As New x264Encoder()
        AEMaxquality.Name = "x264 - AE-Maxquality"
        AEMaxquality.Params.BFrames.Value = 3
        AEMaxquality.Params.BFramesPyramid.Value = True
        AEMaxquality.Params.BFramesWeightedPrediction.Value = True
        AEMaxquality.Params.ReferenceFrames.Value = 16
        AEMaxquality.Params.DeblockAlpha.Value = 1
        AEMaxquality.Params.DeblockBeta.Value = 1
        AEMaxquality.Params.Mode.Value = 4
        AEMaxquality.Params.AdaptiveDCT.Value = True
        AEMaxquality.Params.I8x8.Value = True
        AEMaxquality.Params.SubME.Value = 7
        AEMaxquality.Params.MixedRefs.Value = True
        AEMaxquality.Params.Trellis.Value = 2
        AEMaxquality.Params.MEMethod.Value = 2
        AEMaxquality.Params.BFramesRDO.Value = True
        AEMaxquality.Params.AddAll.Value = "--bime --no-fast-pskip"
        ret.Add(AEMaxquality)

        Dim AEStandard As New x264Encoder()
        AEStandard.Name = "x264 - AE-Standard"
        AEStandard.Params.BFrames.Value = 3
        AEStandard.Params.BFramesPyramid.Value = True
        AEStandard.Params.BFramesWeightedPrediction.Value = True
        AEStandard.Params.ReferenceFrames.Value = 8
        AEStandard.Params.DeblockAlpha.Value = 1
        AEStandard.Params.DeblockBeta.Value = 1
        AEStandard.Params.Mode.Value = 3
        AEStandard.Params.SubME.Value = 5
        AEStandard.Params.MixedRefs.Value = True
        AEStandard.Params.MEMethod.Value = 2
        ret.Add(AEStandard)

        Dim CEBaseline As New x264Encoder()
        CEBaseline.Name = "x264 - CE-Baseline"
        CEBaseline.Params.BFrames.Value = 0
        CEBaseline.Params.BFramesAdaptive.Value = False
        CEBaseline.Params.CABAC.Value = False
        CEBaseline.Params.ReferenceFrames.Value = 1
        CEBaseline.Params.DeblockAlpha.Value = 0
        CEBaseline.Params.DeblockBeta.Value = 0
        CEBaseline.Params.Mode.Value = 3
        ret.Add(CEBaseline)

        Dim CEHighprofile As New x264Encoder()
        CEHighprofile.Name = "x264 - CE-Highprofile"
        CEHighprofile.Params.BFrames.Value = 3
        CEHighprofile.Params.BFramesPyramid.Value = True
        CEHighprofile.Params.BFramesWeightedPrediction.Value = True
        CEHighprofile.Params.ReferenceFrames.Value = 3
        CEHighprofile.Params.DeblockAlpha.Value = 0
        CEHighprofile.Params.DeblockBeta.Value = 0
        CEHighprofile.Params.Mode.Value = 3
        CEHighprofile.Params.AdaptiveDCT.Value = True
        CEHighprofile.Params.I8x8.Value = True
        CEHighprofile.Params.MixedRefs.Value = True
        CEHighprofile.Params.Trellis.Value = 1
        CEHighprofile.Params.BFramesRDO.Value = True
        CEHighprofile.Params.AddAll.Value = "--bime"
        ret.Add(CEHighprofile)

        Dim CEMainprofile As New x264Encoder()
        CEMainprofile.Name = "x264 - CE-Mainprofile"
        CEMainprofile.Params.BFrames.Value = 3
        CEMainprofile.Params.BFramesPyramid.Value = True
        CEMainprofile.Params.BFramesWeightedPrediction.Value = True
        CEMainprofile.Params.ReferenceFrames.Value = 3
        CEMainprofile.Params.DeblockAlpha.Value = 0
        CEMainprofile.Params.DeblockBeta.Value = 0
        CEMainprofile.Params.Mode.Value = 3
        CEMainprofile.Params.MixedRefs.Value = True
        CEMainprofile.Params.Trellis.Value = 1
        CEMainprofile.Params.BFramesRDO.Value = True
        CEMainprofile.Params.AddAll.Value = "--bime"
        ret.Add(CEMainprofile)

        Dim CEQuickTime As New x264Encoder()
        CEQuickTime.Name = "x264 - CE-QuickTime"
        CEQuickTime.Params.BFrames.Value = 1
        CEQuickTime.Params.ReferenceFrames.Value = 5
        CEQuickTime.Params.DeblockAlpha.Value = 0
        CEQuickTime.Params.DeblockBeta.Value = 0
        CEQuickTime.Params.Mode.Value = 3
        CEQuickTime.Params.BFramesRDO.Value = True
        ret.Add(CEQuickTime)

        Dim CQASP_Q2_eq_crf_ As New x264Encoder()
        CQASP_Q2_eq_crf_.Name = "x264 - CQ-ASP_Q2_eq(crf)"
        CQASP_Q2_eq_crf_.Params.BFrames.Value = 3
        CQASP_Q2_eq_crf_.Params.BFramesPyramid.Value = True
        CQASP_Q2_eq_crf_.Params.BFramesWeightedPrediction.Value = True
        CQASP_Q2_eq_crf_.Params.ReferenceFrames.Value = 16
        CQASP_Q2_eq_crf_.Params.DeblockAlpha.Value = -1
        CQASP_Q2_eq_crf_.Params.DeblockBeta.Value = -1
        CQASP_Q2_eq_crf_.Params.Mode.Value = 2
        CQASP_Q2_eq_crf_.Params.Quant.Value = 18
        CQASP_Q2_eq_crf_.Params.AdaptiveDCT.Value = True
        CQASP_Q2_eq_crf_.Params.I8x8.Value = True
        CQASP_Q2_eq_crf_.Params.MixedRefs.Value = True
        CQASP_Q2_eq_crf_.Params.Trellis.Value = 1
        CQASP_Q2_eq_crf_.Params.MEMethod.Value = 2
        CQASP_Q2_eq_crf_.Params.BFramesRDO.Value = True
        CQASP_Q2_eq_crf_.Params.AddAll.Value = "--bime"
        ret.Add(CQASP_Q2_eq_crf_)

        Dim CQASP_Q2_equiv As New x264Encoder()
        CQASP_Q2_equiv.Name = "x264 - CQ-ASP_Q2_equiv"
        CQASP_Q2_equiv.Params.BFrames.Value = 3
        CQASP_Q2_equiv.Params.BFramesPyramid.Value = True
        CQASP_Q2_equiv.Params.BFramesWeightedPrediction.Value = True
        CQASP_Q2_equiv.Params.ReferenceFrames.Value = 16
        CQASP_Q2_equiv.Params.DeblockAlpha.Value = -1
        CQASP_Q2_equiv.Params.DeblockBeta.Value = -1
        CQASP_Q2_equiv.Params.Quant.Value = 18
        CQASP_Q2_equiv.Params.AdaptiveDCT.Value = True
        CQASP_Q2_equiv.Params.I8x8.Value = True
        CQASP_Q2_equiv.Params.MixedRefs.Value = True
        CQASP_Q2_equiv.Params.Trellis.Value = 1
        CQASP_Q2_equiv.Params.MEMethod.Value = 2
        CQASP_Q2_equiv.Params.BFramesRDO.Value = True
        CQASP_Q2_equiv.Params.AddAll.Value = "--bime"
        ret.Add(CQASP_Q2_equiv)

        Dim CQLossless As New x264Encoder()
        CQLossless.Name = "x264 - CQ-Lossless"
        CQLossless.Params.BFrames.Value = 3
        CQLossless.Params.BFramesAdaptive.Value = False
        CQLossless.Params.BFramesPyramid.Value = True
        CQLossless.Params.BFramesWeightedPrediction.Value = True
        CQLossless.Params.ReferenceFrames.Value = 16
        CQLossless.Params.LoopFilter.Value = False
        CQLossless.Params.DeblockAlpha.Value = 0
        CQLossless.Params.DeblockBeta.Value = 0
        CQLossless.Params.Quant.Value = 0
        CQLossless.Params.AdaptiveDCT.Value = True
        CQLossless.Params.I8x8.Value = True
        CQLossless.Params.MixedRefs.Value = True
        CQLossless.Params.Trellis.Value = 2
        CQLossless.Params.MEMethod.Value = 2
        CQLossless.Params.BFramesRDO.Value = True
        ret.Add(CQLossless)

        Dim HQInsane As New x264Encoder()
        HQInsane.Name = "x264 - HQ-Insane"
        HQInsane.Params.BFrames.Value = 3
        HQInsane.Params.BFramesPyramid.Value = True
        HQInsane.Params.BFramesWeightedPrediction.Value = True
        HQInsane.Params.ReferenceFrames.Value = 16
        HQInsane.Params.DeblockBeta.Value = -1
        HQInsane.Params.Mode.Value = 4
        HQInsane.Params.AdaptiveDCT.Value = True
        HQInsane.Params.I8x8.Value = True
        HQInsane.Params.SubME.Value = 7
        HQInsane.Params.MixedRefs.Value = True
        HQInsane.Params.Trellis.Value = 2
        HQInsane.Params.MEMethod.Value = 2
        HQInsane.Params.BFramesRDO.Value = True
        HQInsane.Params.AddAll.Value = "--bime --no-fast-pskip"
        ret.Add(HQInsane)

        Dim HQSlow As New x264Encoder()
        HQSlow.Name = "x264 - HQ-Slow"
        HQSlow.Params.BFrames.Value = 3
        HQSlow.Params.BFramesPyramid.Value = True
        HQSlow.Params.BFramesWeightedPrediction.Value = True
        HQSlow.Params.ReferenceFrames.Value = 5
        HQSlow.Params.DeblockBeta.Value = -1
        HQSlow.Params.Mode.Value = 3
        HQSlow.Params.AdaptiveDCT.Value = True
        HQSlow.Params.I8x8.Value = True
        HQSlow.Params.Trellis.Value = 1
        ret.Add(HQSlow)

        Dim HQSlower As New x264Encoder()
        HQSlower.Name = "x264 - HQ-Slower"
        HQSlower.Params.BFrames.Value = 3
        HQSlower.Params.BFramesPyramid.Value = True
        HQSlower.Params.BFramesWeightedPrediction.Value = True
        HQSlower.Params.ReferenceFrames.Value = 10
        HQSlower.Params.DeblockBeta.Value = -1
        HQSlower.Params.Mode.Value = 3
        HQSlower.Params.AdaptiveDCT.Value = True
        HQSlower.Params.I8x8.Value = True
        HQSlower.Params.MixedRefs.Value = True
        HQSlower.Params.Trellis.Value = 1
        HQSlower.Params.BFramesRDO.Value = True
        HQSlower.Params.AddAll.Value = "--bime"
        ret.Add(HQSlower)

        Dim HQSlowest As New x264Encoder()
        HQSlowest.Name = "x264 - HQ-Slowest"
        HQSlowest.Params.BFrames.Value = 3
        HQSlowest.Params.BFramesPyramid.Value = True
        HQSlowest.Params.BFramesWeightedPrediction.Value = True
        HQSlowest.Params.ReferenceFrames.Value = 16
        HQSlowest.Params.DeblockBeta.Value = -1
        HQSlowest.Params.Mode.Value = 3
        HQSlowest.Params.AdaptiveDCT.Value = True
        HQSlowest.Params.I8x8.Value = True
        HQSlowest.Params.SubME.Value = 7
        HQSlowest.Params.MixedRefs.Value = True
        HQSlowest.Params.Trellis.Value = 1
        HQSlowest.Params.MEMethod.Value = 2
        HQSlowest.Params.BFramesRDO.Value = True
        HQSlowest.Params.AddAll.Value = "--bime"
        ret.Add(HQSlowest)

        Dim PDiPod As New x264Encoder()
        PDiPod.Name = "x264 - PD-iPod"
        PDiPod.Params.BFrames.Value = 0
        PDiPod.Params.BFramesAdaptive.Value = False
        PDiPod.Params.CABAC.Value = False
        PDiPod.Params.ReferenceFrames.Value = 1
        PDiPod.Params.DeblockAlpha.Value = 0
        PDiPod.Params.DeblockBeta.Value = 0
        PDiPod.Params.Mode.Value = 0
        PDiPod.Params.I4x4.Value = False
        PDiPod.Params.P4x4.Value = False
        PDiPod.Params.MEMethod.Value = 2
        PDiPod.Params.AddAll.Value = "--level 1.3 --qpmin 22"
        ret.Add(PDiPod)

        Dim PDPSP As New x264Encoder()
        PDPSP.Name = "x264 - PD-PSP"
        PDPSP.Params.BFrames.Value = 3
        PDPSP.Params.BFramesWeightedPrediction.Value = True
        PDPSP.Params.ReferenceFrames.Value = 2
        PDPSP.Params.DeblockAlpha.Value = 0
        PDPSP.Params.DeblockBeta.Value = 0
        PDPSP.Params.Mode.Value = 3
        PDPSP.Params.MixedRefs.Value = True
        PDPSP.Params.Trellis.Value = 1
        PDPSP.Params.BFramesRDO.Value = True
        ret.Add(PDPSP)

        Dim PDXbox_HiRes As New x264Encoder()
        PDXbox_HiRes.Name = "x264 - PD-Xbox_HiRes"
        PDXbox_HiRes.Params.BFrames.Value = 2
        PDXbox_HiRes.Params.CABAC.Value = False
        PDXbox_HiRes.Params.ReferenceFrames.Value = 1
        PDXbox_HiRes.Params.LoopFilter.Value = False
        PDXbox_HiRes.Params.DeblockAlpha.Value = 0
        PDXbox_HiRes.Params.DeblockBeta.Value = 0
        PDXbox_HiRes.Params.Mode.Value = 3
        PDXbox_HiRes.Params.MEMethod.Value = 2
        PDXbox_HiRes.Params.BFramesRDO.Value = True
        PDXbox_HiRes.Params.AddAll.Value = "--qpmin 18 --qcomp 0.3"
        ret.Add(PDXbox_HiRes)

        Dim PDXbox_LoRes As New x264Encoder()
        PDXbox_LoRes.Name = "x264 - PD-Xbox_LoRes"
        PDXbox_LoRes.Params.BFrames.Value = 3
        PDXbox_LoRes.Params.BFramesPyramid.Value = True
        PDXbox_LoRes.Params.BFramesWeightedPrediction.Value = True
        PDXbox_LoRes.Params.ReferenceFrames.Value = 1
        PDXbox_LoRes.Params.DeblockAlpha.Value = 0
        PDXbox_LoRes.Params.DeblockBeta.Value = 0
        PDXbox_LoRes.Params.Mode.Value = 3
        PDXbox_LoRes.Params.Trellis.Value = 1
        PDXbox_LoRes.Params.MEMethod.Value = 2
        PDXbox_LoRes.Params.BFramesRDO.Value = True
        PDXbox_LoRes.Params.AddAll.Value = "--qpmin 18 --qcomp 0.3"
        ret.Add(PDXbox_LoRes)

        Dim x264cli As New CLIEncoder(StaxRip.StreamType.RAW264)
        x264cli.Name = "Misc - Command Line Example"
        x264cli.Muxer = New MP4BoxMuxer
        x264cli.CommandLines = """%application:x264%"" --pass 1 --bitrate %video_bitrate% --stats ""%source_temp_dir%%target_name%.stats"" --bframes 3 --b-pyramid --filter -2:-1 --progress --no-psnr --subme 1 --analyse none --me dia --ref 1 --output NUL ""%source_dir%%target_name%.avs""" + vbCrLf + """%application:x264%"" --pass 2 --bitrate %video_bitrate% --stats ""%source_temp_dir%%target_name%.stats"" --ref 5 --bframes 3 --b-pyramid --weightb --filter -2:-1 --analyse all --8x8dct --subme 6 --trellis 1 --progress --no-psnr --output ""%encoder_out_file%"" ""%source_dir%%target_name%.avs"""
        x264cli.CompCheckCommandLines = """%application:x264%"" --qp 18 --ref 5 --bframes 3 --b-pyramid --weightb --filter -2:-1 --analyse all --8x8dct --subme 6 --trellis 1 --progress --no-psnr --output ""%source_temp_dir%%target_name%_CompCheck%encoder_ext%"" ""%source_temp_dir%%target_name%_CompCheck.avs"""
        ret.Add(x264cli)

        ret.Add(New NullEncoder("Misc - No Encoding"))

        Return ret
    End Function

    Public Function CompareToVideoEncoder(ByVal other As VideoEncoder) As Integer Implements System.IComparable(Of VideoEncoder).CompareTo
        Return Name.CompareTo(other.Name)
    End Function

    Public Overridable Sub StartCompCheck()
    End Sub

    Public Overrides Function GetInfoValues() As Dictionary(Of String, String)
        Dim ret As New Dictionary(Of String, String)

        ret("Encoder Type") = TypeName
        ret("Output File Extension") = GetExtension()
        ret("Muxer Type") = Muxer.TypeName
        ret("Output Format") = StreamTypeUtils.GetName(OutputStreamType)

        Return ret
    End Function

    Public Overrides Function Edit() As DialogResult
        Dim f As New ProfileControlForm(Name)
        f.pControl.Controls.Add(EditControl)
        f.ShowDialog()
        f.Dispose()

        Return DialogResult.OK
    End Function
End Class

<Serializable()> _
Public MustInherit Class VirtualDubEncoder
    Inherits VideoEncoder

    Protected VDMSetCompression As String
    Protected RegistryKey As String
    Protected RegistryRoot As RegistryRoot

    Public RegFirstPass As New SortedList
    Public RegSecondPass As New SortedList
    Public RegCompCheck As New SortedList

    Protected MustOverride Function VerifyRequirements() As Boolean
    Public MustOverride Sub ModifyValues(ByVal sl As SortedList)

    Public Sub New(ByVal name As String, ByVal typeName As String)
        MyBase.New(name, typeName)
        Muxer = New EncoderMuxer("AVI - VirtualDubMod", StaxRip.StreamType.AVI, New StreamType() {StreamType.AC3, StreamType.MP3CBR, StreamType.MP3VBR, StreamType.AVI}, GetType(VirtualDubEncoder), True)
        OutputStreamType = StaxRip.StreamType.AVI
        IsCompCheckEnabledValue = True
    End Sub

    Private SupportedPassesValue As Integer

    Public Property SupportedPasses() As Integer
        Get
            Return SupportedPassesValue
        End Get
        Set(ByVal Value As Integer)
            SupportedPassesValue = Value
        End Set
    End Property

    Private FourCCValue As String

    Public Property FourCC() As String
        Get
            Return FourCCValue
        End Get
        Set(ByVal Value As String)
            FourCCValue = Value
        End Set
    End Property

    Private UseVirtualDubValue As Boolean

    Public Property UseVirtualDub() As Boolean
        Get
            Return UseVirtualDubValue
        End Get
        Set(ByVal Value As Boolean)
            UseVirtualDubValue = Value
        End Set
    End Property

    Public Overrides Sub StartCompCheck()
        If Not VerifyRequirements() Then Exit Sub
        If Not g.IsValidSource Then Exit Sub

        ProcessForm.ShowForm(False)
        Log.WriteHeader("Compressibility Check")

        Dim vd As New VirtualDubScript
        Dim script As String = Macro.Solve(p.TargetAVSDoc.GetScript) + vbCrLf

        script += "SelectRangeEvery(" + ((100 \ p.CompCheckRange.Value) * 14).ToString + ",14)" + vbCrLf

        StringHelp.WriteFile(Paths.GetTempDir() + p.Name + "_CompCheck.avs", script)

        SetReg(RegCompCheck)

        vd.Open(Paths.GetTempDir() + p.Name + "_CompCheck.avs")
        vd.VideoSetModeFastRecompress()
        vd.VideoSetCompression(VDMSetCompression, 0)
        vd.Save(Paths.GetTempDir() + p.Name + "_CompCheck.avi")
        vd.SaveScript(Paths.GetTempDir() + p.Name + "_CompCheck.vcf")

        Dim pw As New ProcessWrapper

        pw.File = GetVirtualDubModPath()
        pw.Arguments = "/s""" + Paths.GetTempDir() + p.Name + "_CompCheck.vcf"" /x"
        pw.Minimized = s.RunAppsMinimized.Value
        pw.Wait = True
        pw.Priority = s.ProcessPriority.Value

        ProcessForm.ProcessWrapper = pw

        Try
            pw.Start()
        Catch ex As AbortException
            ProcessForm.CloseProcessForm()
            Exit Sub
        End Try

        Dim bits As Long = (New FileInfo(Paths.GetTempDir() + p.Name + "_CompCheck.avi").Length) * 8
        Dim af As New AVIFile

        af.Open(Paths.GetTempDir() + p.Name + "_CompCheck.avs")
        p.Compressibility = (bits / af.FrameCount) / (p.TargetWidth * p.TargetHeight)
        af.Close()

        OnAfterCompCheck()

        g.MainForm.UpdateControls()
        g.MainForm.Assistant()

        Log.WriteLine(CInt(Calc.GetPercent).ToString() + " %")

        ProcessForm.CloseProcessForm()
    End Sub

    Public Overrides Sub Encode()
        Dim startTime As DateTime
        Dim script As New VirtualDubScript

        If Passes > 1 Then
            Log.WriteHeader("First Pass Codec Parameters")
            SetReg(RegFirstPass)
            script.Open(p.TargetAVSDoc.Path)
            script.VideoSetModeFastRecompress()
            script.VideoSetCompression(VDMSetCompression, p.VideoBitrate / 8)
            script.Save(Paths.GetTempDir + p.Name + "_FirstPass.avi")

            Log.WriteHeader("First Pass Encoding")
            Log.AddLines(script.Text)

            script.SaveScript(Paths.GetTempDir + p.Name + "_FirstPass.vcf")
            startTime = DateTime.Now

            Dim pw As New ProcessWrapper
            ProcessForm.ProcessWrapper = pw
            p.TargetAVSDoc.Synchronize()

            pw.File = GetVirtualDubModPath()
            pw.Arguments = "/s""" + Paths.GetTempDir + p.Name + "_FirstPass.vcf"" /x"
            pw.Minimized = s.RunAppsMinimized.Value
            pw.Wait = True
            pw.Priority = s.ProcessPriority.Value
            pw.Start()

            Log.WriteHeader("First Pass Encoding Statistics")
            Log.WriteStats(startTime, p.TargetAVSDoc.GetFrames)
        End If

        Dim index As Integer = Passes

        If Passes > 1 Then
            index -= 1
        End If

        For i As Integer = 1 To index
            Log.WriteHeader("Single, Second or NTh Pass Codec Parameters")
            SetReg(RegSecondPass)
            script.Open(p.TargetAVSDoc.Path)

            If Not UseVirtualDub Then
                script.RemoveInputStreams()
            End If

            script.VideoSetModeFastRecompress()
            script.VideoSetCompression(VDMSetCompression, p.VideoBitrate / 8)

            If TypeOf Muxer Is EncoderMuxer AndAlso Not UseVirtualDub Then
                Dim indexTrack2 As Integer

                If p.Audio0.File <> "" AndAlso Muxer.IsStreamSupported(p.Audio0.Profile.StreamType) Then
                    indexTrack2 = 1
                    script.StreamSetSource(0, p.Audio0.File, p.Audio0.Profile.StreamType)
                    script.StreamSetMode(0, AudioMode.DirectStreamCopy)

                    If Not p.Audio0.Profile.HandlesDelay AndAlso p.Audio0.Delay <> 0 Then
                        script.StreamSetInterleave(0, p.Audio0.Delay)
                    End If
                End If

                If p.Audio1.File <> "" AndAlso Muxer.IsStreamSupported(p.Audio1.Profile.StreamType) Then
                    script.StreamSetSource(indexTrack2, p.Audio1.File, p.Audio1.Profile.StreamType)
                    script.StreamSetMode(indexTrack2, AudioMode.DirectStreamCopy)

                    If Not p.Audio1.Profile.HandlesDelay AndAlso p.Audio1.Delay <> 0 Then
                        script.StreamSetInterleave(1, p.Audio1.Delay)
                    End If
                End If
            End If

            script.Save(OutputPath)

            Log.WriteHeader("Single, Second or NTh Pass Encoding")
            Log.AddLines(script.Text)

            script.SaveScript(Paths.GetTempDir + p.Name + "_SecondPass.vcf")
            startTime = DateTime.Now

            Dim pw As New ProcessWrapper
            ProcessForm.ProcessWrapper = pw
            p.TargetAVSDoc.Synchronize()

            pw.File = GetVirtualDubModPath()
            pw.Arguments = "/s""" + Paths.GetTempDir + p.Name + "_SecondPass.vcf"" /x"
            pw.Minimized = s.RunAppsMinimized.Value
            pw.Wait = True
            pw.Priority = s.ProcessPriority.Value
            pw.Start()

            Log.WriteHeader("Single, Second or NTh Pass Encoding Statistics")
            Log.WriteStats(startTime, p.TargetAVSDoc.GetFrames)
        Next
    End Sub

    Public Function GetVirtualDubModPath() As String
        If UseVirtualDub Then
            Return Paths.Packages("VirtualDub").GetPath(False)
        Else
            Return Paths.Packages("VirtualDubMod").GetPath(False)
        End If
    End Function

    Private Sub ShowOptionsDialog()
        Dim f As New VirtualDubEncoderOptionsForm(Me)
        f.ShowDialog()
        f.Dispose()
        OnStateChange()
    End Sub

    Public Sub SetRegList(ByVal key As String, ByVal value As Object)
        SetRegList(key, value, Modes.CompCheck Or Modes.First Or Modes.Second)
    End Sub

    Public Sub SetRegList(ByVal key As String, ByVal value As Object, ByVal flags As Modes)
        If (flags And Modes.First) = Modes.First Then
            RegFirstPass(key) = value
        End If

        If (flags And Modes.Second) = Modes.Second Then
            RegSecondPass(key) = value
        End If

        If (flags And Modes.CompCheck) = Modes.CompCheck Then
            RegCompCheck(key) = value
        End If
    End Sub

    Public Sub ShowFirstPassDialog(ByVal owner As IntPtr)
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        VFW.ShowEncoderForm(FourCC, owner)
        RegFirstPass = GetRegAll()
    End Sub

    Public Sub ShowSecondPassDialog(ByVal owner As IntPtr)
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        VFW.ShowEncoderForm(FourCC, owner)
        RegSecondPass = GetRegAll()
    End Sub

    Public Sub ShowCompCheckDialog(ByVal owner As IntPtr)
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        VFW.ShowEncoderForm(FourCC, owner)
        RegCompCheck = GetRegAll()
    End Sub

    Public Sub SetReg(ByVal name As String, ByVal value As Object)
        If RegistryRoot = RegistryRoot.CurrentUser Then
            Registry.CurrentUser.CreateSubKey(RegistryKey).SetValue(name, value)
        ElseIf RegistryRoot = RegistryRoot.LocalMachine Then
            Registry.LocalMachine.CreateSubKey(RegistryKey).SetValue(name, value)
        End If

        If TypeOf value Is IConvertible Then
            Log.WriteLine(name + ": " + CStr(value))
        End If
    End Sub

    Public Sub SetReg(ByVal sl As SortedList)
        If Not sl Is Nothing Then
            ModifyValues(sl)

            For Each i As String In sl.Keys
                SetReg(i, sl(i))
            Next
        End If
    End Sub

    Public Function GetReg(ByVal key As String, ByVal subkey As String) As Object
        If RegistryRoot = RegistryRoot.CurrentUser Then
            Return Registry.CurrentUser.OpenSubKey(key).GetValue(subkey)
        ElseIf RegistryRoot = RegistryRoot.LocalMachine Then
            Return Registry.LocalMachine.OpenSubKey(key).GetValue(subkey)
        End If

        Return Nothing
    End Function

    Protected Function GetRegAll() As SortedList
        Dim sl As New SortedList
        Dim st As String

        If RegistryRoot = RegistryRoot.CurrentUser Then
            For Each st In Registry.CurrentUser.CreateSubKey(RegistryKey).GetValueNames
                sl.Add(st, GetReg(RegistryKey, st))
            Next
        ElseIf RegistryRoot = RegistryRoot.LocalMachine Then
            For Each st In Registry.LocalMachine.CreateSubKey(RegistryKey).GetValueNames
                sl.Add(st, GetReg(RegistryKey, st))
            Next
        End If

        Return sl
    End Function

    Public Sub ShowFirstPassOptionsDialog()
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        SetReg(RegFirstPass)
        ShowFirstPassDialog(g.MainForm.Handle)
    End Sub

    Public Sub ShowSecondPassOptionsDialog()
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        SetReg(RegSecondPass)
        ShowSecondPassDialog(g.MainForm.Handle)
    End Sub

    Public Sub ShowCompCheckOptionsDialog()
        If Not VerifyRequirements() Then
            Exit Sub
        End If

        SetReg(RegCompCheck)
        ShowCompCheckDialog(g.MainForm.Handle)
    End Sub

    Public Overrides Function GetMenu() As List(Of OptionListBoxItem)
        Dim ret As New List(Of OptionListBoxItem)

        If Passes = 1 Then
            Dim secondPassDialog As New OptionListBoxItem
            secondPassDialog.Text = "Codec Configuration"
            secondPassDialog.Description = "Opens the codec configuration dialog."
            secondPassDialog.ClickSub = AddressOf ShowSecondPassOptionsDialog
            ret.Add(secondPassDialog)
        Else
            Dim firstPassDialog As New OptionListBoxItem
            firstPassDialog.Text = "First Pass"
            firstPassDialog.Description = "Opens the configuration dialog for the first pass. The first pass performs a analysis."
            firstPassDialog.ClickSub = AddressOf ShowFirstPassOptionsDialog
            ret.Add(firstPassDialog)

            Dim secondPassDialog As New OptionListBoxItem
            secondPassDialog.Text = "Second Pass"
            secondPassDialog.Description = "Opens the configuration dialog for the second pass. The second pass performs the encoding."
            secondPassDialog.ClickSub = AddressOf ShowSecondPassOptionsDialog
            ret.Add(secondPassDialog)
        End If

        If Not QualityMode Then
            Dim compCheckDialog As New OptionListBoxItem
            compCheckDialog.Text = "Compressibility Check"
            compCheckDialog.Description = "Opens the configuration dialog for the compressibility check. The compressibility check helps to find a optimal bitrate."
            compCheckDialog.ClickSub = AddressOf ShowCompCheckOptionsDialog
            ret.Add(compCheckDialog)

            Dim startCompCheckDialog As New OptionListBoxItem
            startCompCheckDialog.Text = "Run Compressibility Check"
            startCompCheckDialog.Description = "Runs the compressibility check. The compressibility check helps to find a optimal bitrate."
            startCompCheckDialog.ClickSub = AddressOf StartCompCheck
            ret.Add(startCompCheckDialog)
        End If

        Dim muxConfig As New OptionListBoxItem
        muxConfig.Text = "Container Configuration"
        muxConfig.Description = "Opens the container configuration dialog."
        muxConfig.ClickSub = AddressOf OpenMuxerConfigDialog
        ret.Add(muxConfig)

        Dim optionsDialog As New OptionListBoxItem
        optionsDialog.Text = "Options"
        optionsDialog.Description = "Opens the encoder options dialog."
        optionsDialog.ClickSub = AddressOf ShowOptionsDialog
        ret.Add(optionsDialog)

        Return ret
    End Function
End Class

<Serializable()> _
Public Class XviDVirtualDubEncoder
    Inherits VirtualDubEncoder

    Public Sub New()
        MyBase.New("XviD", "XviD VirtualDub(Mod) Encoder")
        AutoCompCheckValue = 80
        RegistryKey = "Software\GNU\XviD"
        FourCC = "xvid"
        VDMSetCompression = "0x64697678,0,10000,0"
        SupportedPasses = 2
        RegistryRoot = RegistryRoot.CurrentUser
    End Sub

    Public Sub SetTwoPassRegDefaults()
        RegFirstPass.Clear()

        RegFirstPass("ar_mode") = 0
        RegFirstPass("ar_x") = 4
        RegFirstPass("ar_y") = 3
        RegFirstPass("aspect_ratio") = 0
        RegFirstPass("audio_mode") = 0
        RegFirstPass("audio_rate") = 128
        RegFirstPass("audio_size") = 0
        RegFirstPass("audio_type") = 0
        RegFirstPass("bitrate") = 700
        RegFirstPass("bquant_offset") = 100
        RegFirstPass("bquant_ratio") = 150
        RegFirstPass("Brightness") = 0
        RegFirstPass("chromame") = 1
        RegFirstPass("container_type") = 1
        RegFirstPass("curve_compression_high") = 0
        RegFirstPass("curve_compression_low") = 0
        RegFirstPass("Deblock_UV") = 0
        RegFirstPass("Deblock_Y") = 0
        RegFirstPass("debug") = 0
        RegFirstPass("Dering_UV") = 0
        RegFirstPass("Dering_Y") = 0
        RegFirstPass("desired_quant") = 200
        RegFirstPass("desired_size") = 570000
        RegFirstPass("discard1pass") = 1
        RegFirstPass("display_status") = 0
        RegFirstPass("FilmEffect") = 0
        RegFirstPass("fourcc_used") = 0
        RegFirstPass("fps") = 2
        RegFirstPass("frame_drop_ratio") = 0
        RegFirstPass("full1pass") = 0
        RegFirstPass("gmc") = 0
        RegFirstPass("hours") = 1
        RegFirstPass("interlacing") = 0
        RegFirstPass("keyframe_boost") = 10
        RegFirstPass("kfreduction") = 20
        RegFirstPass("kfthreshold") = 1
        RegFirstPass("lum_masking") = 0
        RegFirstPass("max_bframes") = 2
        RegFirstPass("max_bquant") = 31
        RegFirstPass("max_iquant") = 31
        RegFirstPass("max_key_interval") = 300
        RegFirstPass("max_pquant") = 31
        RegFirstPass("min_bquant") = 1
        RegFirstPass("min_iquant") = 1
        RegFirstPass("min_pquant") = 1
        RegFirstPass("minutes") = 30
        RegFirstPass("mode") = 1
        RegFirstPass("motion_search") = 6
        RegFirstPass("num_zones") = 1
        RegFirstPass("overflow_control_strength") = 5
        RegFirstPass("packed") = 1
        RegFirstPass("par_x") = 1
        RegFirstPass("par_y") = 1
        RegFirstPass("profile") = "Home Theatre PAL"
        RegFirstPass("qmatrix_inter") = New Byte() {16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33}
        RegFirstPass("qmatrix_intra") = New Byte() {8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28, 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32, 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38, 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45}
        RegFirstPass("qpel") = 0
        RegFirstPass("quality") = "General purpose"
        RegFirstPass("quant_type") = 0
        RegFirstPass("rc_averaging_period") = 100
        RegFirstPass("rc_buffer") = 100
        RegFirstPass("rc_reaction_delay_factor") = 16
        RegFirstPass("seconds") = 0
        RegFirstPass("stats") = "\video.pass"
        RegFirstPass("subtitle_size") = 0
        RegFirstPass("target_size") = 665600
        RegFirstPass("tff") = 0
        RegFirstPass("trellis_quant") = 1
        RegFirstPass("turbo") = 0
        RegFirstPass("twopass_max_overflow_degradation") = 5
        RegFirstPass("twopass_max_overflow_improvement") = 5
        RegFirstPass("use_2pass_bitrate") = 0
        RegFirstPass("use_bvop") = 1
        RegFirstPass("vhq_bframe") = 0
        RegFirstPass("vhq_mode") = 1
        RegFirstPass("vop_debug") = 0
        RegFirstPass("zone0_bvop_threshold") = 0
        RegFirstPass("zone0_cartoon_mode") = 0
        RegFirstPass("zone0_chroma_opt") = 0
        RegFirstPass("zone0_frame") = 0
        RegFirstPass("zone0_greyscale") = 0
        RegFirstPass("zone0_mode") = 0
        RegFirstPass("zone0_quant") = 500
        RegFirstPass("zone0_type") = 0
        RegFirstPass("zone0_weight") = 100

        RegSecondPass.Clear()

        RegSecondPass("ar_mode") = 0
        RegSecondPass("ar_x") = 4
        RegSecondPass("ar_y") = 3
        RegSecondPass("aspect_ratio") = 0
        RegSecondPass("audio_mode") = 0
        RegSecondPass("audio_rate") = 128
        RegSecondPass("audio_size") = 0
        RegSecondPass("audio_type") = 0
        RegSecondPass("bitrate") = 1000
        RegSecondPass("bquant_offset") = 100
        RegSecondPass("bquant_ratio") = 150
        RegSecondPass("Brightness") = 0
        RegSecondPass("chromame") = 1
        RegSecondPass("container_type") = 1
        RegSecondPass("curve_compression_high") = 0
        RegSecondPass("curve_compression_low") = 0
        RegSecondPass("Deblock_UV") = 0
        RegSecondPass("Deblock_Y") = 0
        RegSecondPass("debug") = 0
        RegSecondPass("Dering_UV") = 0
        RegSecondPass("Dering_Y") = 0
        RegSecondPass("desired_quant") = 200
        RegSecondPass("desired_size") = 570000
        RegSecondPass("discard1pass") = 1
        RegSecondPass("display_status") = 0
        RegSecondPass("FilmEffect") = 0
        RegSecondPass("fourcc_used") = 0
        RegSecondPass("fps") = 2
        RegSecondPass("frame_drop_ratio") = 0
        RegSecondPass("full1pass") = 0
        RegSecondPass("gmc") = 0
        RegSecondPass("hours") = 1
        RegSecondPass("interlacing") = 0
        RegSecondPass("keyframe_boost") = 10
        RegSecondPass("kfreduction") = 20
        RegSecondPass("kfthreshold") = 1
        RegSecondPass("lum_masking") = 0
        RegSecondPass("max_bframes") = 2
        RegSecondPass("max_bquant") = 31
        RegSecondPass("max_iquant") = 31
        RegSecondPass("max_key_interval") = 300
        RegSecondPass("max_pquant") = 31
        RegSecondPass("min_bquant") = 1
        RegSecondPass("min_iquant") = 1
        RegSecondPass("min_pquant") = 1
        RegSecondPass("minutes") = 30
        RegSecondPass("mode") = 2
        RegSecondPass("motion_search") = 6
        RegSecondPass("num_zones") = 1
        RegSecondPass("overflow_control_strength") = 5
        RegSecondPass("packed") = 1
        RegSecondPass("par_x") = 1
        RegSecondPass("par_y") = 1
        RegSecondPass("profile") = "Home Theatre PAL"
        RegSecondPass("qmatrix_inter") = New Byte() {16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33}
        RegSecondPass("qmatrix_intra") = New Byte() {8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28, 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32, 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38, 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45}
        RegSecondPass("qpel") = 0
        RegSecondPass("quality") = "General purpose"
        RegSecondPass("quant_type") = 0
        RegSecondPass("rc_averaging_period") = 100
        RegSecondPass("rc_buffer") = 100
        RegSecondPass("rc_reaction_delay_factor") = 16
        RegSecondPass("seconds") = 0
        RegSecondPass("stats") = "\video.pass"
        RegSecondPass("subtitle_size") = 0
        RegSecondPass("target_size") = 665600
        RegSecondPass("tff") = 0
        RegSecondPass("trellis_quant") = 1
        RegSecondPass("turbo") = 0
        RegSecondPass("twopass_max_overflow_degradation") = 5
        RegSecondPass("twopass_max_overflow_improvement") = 5
        RegSecondPass("use_2pass_bitrate") = 1
        RegSecondPass("use_bvop") = 1
        RegSecondPass("vhq_bframe") = 0
        RegSecondPass("vhq_mode") = 1
        RegSecondPass("vop_debug") = 0
        RegSecondPass("zone0_bvop_threshold") = 0
        RegSecondPass("zone0_cartoon_mode") = 0
        RegSecondPass("zone0_chroma_opt") = 0
        RegSecondPass("zone0_frame") = 0
        RegSecondPass("zone0_greyscale") = 0
        RegSecondPass("zone0_mode") = 0
        RegSecondPass("zone0_quant") = 500
        RegSecondPass("zone0_type") = 0
        RegSecondPass("zone0_weight") = 100
    End Sub

    Public Sub SetQualityModeRegDefaults()
        RegSecondPass.Clear()

        RegSecondPass("ar_mode") = 0
        RegSecondPass("ar_x") = 4
        RegSecondPass("ar_y") = 3
        RegSecondPass("aspect_ratio") = 0
        RegSecondPass("audio_mode") = 0
        RegSecondPass("audio_rate") = 128
        RegSecondPass("audio_size") = 0
        RegSecondPass("audio_type") = 0
        RegSecondPass("bitrate") = 700
        RegSecondPass("bquant_offset") = 100
        RegSecondPass("bquant_ratio") = 150
        RegSecondPass("Brightness") = 0
        RegSecondPass("chromame") = 1
        RegSecondPass("container_type") = 1
        RegSecondPass("curve_compression_high") = 0
        RegSecondPass("curve_compression_low") = 0
        RegSecondPass("Deblock_UV") = 0
        RegSecondPass("Deblock_Y") = 0
        RegSecondPass("debug") = 0
        RegSecondPass("Dering_UV") = 0
        RegSecondPass("Dering_Y") = 0
        RegSecondPass("desired_quant") = 300
        RegSecondPass("desired_size") = 570000
        RegSecondPass("discard1pass") = 1
        RegSecondPass("display_status") = 0
        RegSecondPass("FilmEffect") = 0
        RegSecondPass("fourcc_used") = 0
        RegSecondPass("fps") = 2
        RegSecondPass("frame_drop_ratio") = 0
        RegSecondPass("full1pass") = 0
        RegSecondPass("gmc") = 0
        RegSecondPass("hours") = 1
        RegSecondPass("interlacing") = 0
        RegSecondPass("keyframe_boost") = 10
        RegSecondPass("kfreduction") = 20
        RegSecondPass("kfthreshold") = 1
        RegSecondPass("lum_masking") = 0
        RegSecondPass("max_bframes") = 2
        RegSecondPass("max_bquant") = 31
        RegSecondPass("max_iquant") = 31
        RegSecondPass("max_key_interval") = 300
        RegSecondPass("max_pquant") = 31
        RegSecondPass("min_bquant") = 1
        RegSecondPass("min_iquant") = 1
        RegSecondPass("min_pquant") = 1
        RegSecondPass("minutes") = 30
        RegSecondPass("mode") = 0
        RegSecondPass("motion_search") = 6
        RegSecondPass("num_zones") = 1
        RegSecondPass("overflow_control_strength") = 5
        RegSecondPass("packed") = 1
        RegSecondPass("par_x") = 1
        RegSecondPass("par_y") = 1
        RegSecondPass("profile") = "Home Theatre PAL"
        RegSecondPass("qmatrix_inter") = New Byte() {16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33}
        RegSecondPass("qmatrix_intra") = New Byte() {8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28, 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32, 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38, 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45}
        RegSecondPass("qpel") = 0
        RegSecondPass("quality") = "General purpose"
        RegSecondPass("quant_type") = 0
        RegSecondPass("rc_averaging_period") = 100
        RegSecondPass("rc_buffer") = 100
        RegSecondPass("rc_reaction_delay_factor") = 16
        RegSecondPass("seconds") = 0
        RegSecondPass("stats") = "\video.pass"
        RegSecondPass("subtitle_size") = 0
        RegSecondPass("target_size") = 665600
        RegSecondPass("tff") = 0
        RegSecondPass("trellis_quant") = 1
        RegSecondPass("turbo") = 0
        RegSecondPass("twopass_max_overflow_degradation") = 5
        RegSecondPass("twopass_max_overflow_improvement") = 5
        RegSecondPass("use_2pass_bitrate") = 0
        RegSecondPass("use_bvop") = 1
        RegSecondPass("vhq_bframe") = 0
        RegSecondPass("vhq_mode") = 1
        RegSecondPass("vop_debug") = 0
        RegSecondPass("zone0_bvop_threshold") = 0
        RegSecondPass("zone0_cartoon_mode") = 0
        RegSecondPass("zone0_chroma_opt") = 0
        RegSecondPass("zone0_frame") = 0
        RegSecondPass("zone0_greyscale") = 0
        RegSecondPass("zone0_mode") = 0
        RegSecondPass("zone0_quant") = 500
        RegSecondPass("zone0_type") = 0
        RegSecondPass("zone0_weight") = 100
    End Sub

    Public Sub SetCompCheckRegDefaults()
        RegCompCheck.Clear()

        RegCompCheck("ar_mode") = 0
        RegCompCheck("ar_x") = 4
        RegCompCheck("ar_y") = 3
        RegCompCheck("aspect_ratio") = 0
        RegCompCheck("audio_mode") = 0
        RegCompCheck("audio_rate") = 128
        RegCompCheck("audio_size") = 0
        RegCompCheck("audio_type") = 0
        RegCompCheck("bitrate") = 700
        RegCompCheck("bquant_offset") = 100
        RegCompCheck("bquant_ratio") = 150
        RegCompCheck("Brightness") = 0
        RegCompCheck("chromame") = 1
        RegCompCheck("container_type") = 1
        RegCompCheck("curve_compression_high") = 0
        RegCompCheck("curve_compression_low") = 0
        RegCompCheck("Deblock_UV") = 0
        RegCompCheck("Deblock_Y") = 0
        RegCompCheck("debug") = 0
        RegCompCheck("Dering_UV") = 0
        RegCompCheck("Dering_Y") = 0
        RegCompCheck("desired_quant") = 200
        RegCompCheck("desired_size") = 570000
        RegCompCheck("discard1pass") = 1
        RegCompCheck("display_status") = 0
        RegCompCheck("FilmEffect") = 0
        RegCompCheck("fourcc_used") = 0
        RegCompCheck("fps") = 2
        RegCompCheck("frame_drop_ratio") = 0
        RegCompCheck("full1pass") = 0
        RegCompCheck("gmc") = 0
        RegCompCheck("hours") = 1
        RegCompCheck("interlacing") = 0
        RegCompCheck("keyframe_boost") = 10
        RegCompCheck("kfreduction") = 20
        RegCompCheck("kfthreshold") = 1
        RegCompCheck("lum_masking") = 0
        RegCompCheck("max_bframes") = 2
        RegCompCheck("max_bquant") = 31
        RegCompCheck("max_iquant") = 31
        RegCompCheck("max_key_interval") = 300
        RegCompCheck("max_pquant") = 31
        RegCompCheck("min_bquant") = 1
        RegCompCheck("min_iquant") = 1
        RegCompCheck("min_pquant") = 1
        RegCompCheck("minutes") = 30
        RegCompCheck("mode") = 0
        RegCompCheck("motion_search") = 6
        RegCompCheck("num_zones") = 1
        RegCompCheck("overflow_control_strength") = 5
        RegCompCheck("packed") = 1
        RegCompCheck("par_x") = 1
        RegCompCheck("par_y") = 1
        RegCompCheck("profile") = "Home Theatre PAL"
        RegCompCheck("qmatrix_inter") = New Byte() {16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33}
        RegCompCheck("qmatrix_intra") = New Byte() {8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28, 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32, 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38, 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45}
        RegCompCheck("qpel") = 0
        RegCompCheck("quality") = "General purpose"
        RegCompCheck("quant_type") = 0
        RegCompCheck("rc_averaging_period") = 100
        RegCompCheck("rc_buffer") = 100
        RegCompCheck("rc_reaction_delay_factor") = 16
        RegCompCheck("seconds") = 0
        RegCompCheck("stats") = "\video.pass"
        RegCompCheck("subtitle_size") = 0
        RegCompCheck("target_size") = 665600
        RegCompCheck("tff") = 0
        RegCompCheck("trellis_quant") = 1
        RegCompCheck("turbo") = 0
        RegCompCheck("twopass_max_overflow_degradation") = 5
        RegCompCheck("twopass_max_overflow_improvement") = 5
        RegCompCheck("use_2pass_bitrate") = 0
        RegCompCheck("use_bvop") = 1
        RegCompCheck("vhq_bframe") = 0
        RegCompCheck("vhq_mode") = 1
        RegCompCheck("vop_debug") = 0
        RegCompCheck("zone0_bvop_threshold") = 0
        RegCompCheck("zone0_cartoon_mode") = 0
        RegCompCheck("zone0_chroma_opt") = 0
        RegCompCheck("zone0_frame") = 0
        RegCompCheck("zone0_greyscale") = 0
        RegCompCheck("zone0_mode") = 0
        RegCompCheck("zone0_quant") = 500
        RegCompCheck("zone0_type") = 0
        RegCompCheck("zone0_weight") = 100
    End Sub

    Private Sub Verify()
        If Passes = 1 Then
            If CInt(RegSecondPass("mode")) <> XviDPasses.Single Then
                SetQualityModeRegDefaults()
            End If
        Else
            If CInt(RegSecondPass("mode")) <> XviDPasses.Second Then
                SetTwoPassRegDefaults()
            End If
        End If

        If CInt(RegCompCheck("mode")) <> XviDPasses.Single Then
            SetCompCheckRegDefaults()
        End If
    End Sub

    Public Overrides Sub ModifyValues(ByVal sl As SortedList)
        Verify()
        Dim frames As Integer = p.TargetAVSDoc.GetFrames
        Dim rate As Double = frames / p.TargetSeconds
        Dim desired_size As Integer = CInt((((p.VideoBitrate * p.TargetSeconds) / 8) / 1.024) + (p.TargetSeconds * rate * 0.024))
        sl("desired_size") = desired_size
        sl("stats") = Paths.GetTempDir + p.Name + ".pass"
        sl("bitrate") = CInt(p.VideoBitrate + ((frames * 0.024 * 8 * 1.024) / p.TargetSeconds))

        If p.AutoARSignaling.Value Then
            If ARCalc.IsARSignalingRequired Then
                sl("aspect_ratio") = 5
                sl("par_x") = ARCalc.GetPARForY100()
                sl("par_y") = 100
            Else
                sl("aspect_ratio") = 0
                sl("par_x") = 1
                sl("par_y") = 1
            End If
        End If
    End Sub

    Public Enum XviDPasses
        [Single]
        First
        Second
    End Enum

    Protected Overrides Function VerifyRequirements() As Boolean
        If Not Paths.VerifyRequirements Then
            Return False
        End If

        If Not Paths.XviD.VerifyOK(False) Then
            Return False
        End If

        If UseVirtualDub Then
            If Not Paths.VirtualDub.VerifyOK(False) Then
                Return False
            End If
        Else
            If Not Paths.VirtualDubMod.VerifyOK(False) Then
                Return False
            End If
        End If

        Return True
    End Function
End Class

<Serializable()> _
Public Class DivXVirtualDubEncoder
    Inherits VirtualDubEncoder

    Private VersionDate As DateTime
    Private BuildName As String

    Public Sub New()
        MyBase.New("DivX", "DivX VirtualDub(Mod) Encoder")
        AutoCompCheckValue = 80
        RegistryKey = "Software\DivXNetworks\DivX4Windows\State"
        FourCC = "divx"
        VDMSetCompression = "0x78766964,0,10000,0"
        SupportedPasses = 3
        Passes = 2
        RegistryRoot = RegistryRoot.CurrentUser
        Verify()
    End Sub

    Public Sub Verify()
        Dim dir As String = Filepath.AppendSeparator(RegistryHelp.LocalMachine.GetString("SOFTWARE\DivXNetworks\DivX", "uninstdir")) + "DivX"

        If Not Directory.Exists(dir) Then
            Exit Sub
        End If

        Dim k As RegistryKey = Registry.CurrentUser.OpenSubKey(RegistryKey, True)

        If Not k Is Nothing Then
            k.SetValue(Nothing, "")
        End If

        Dim h As Integer = VFW.GetEncoderHandle(FourCC, VFW.ICMODE.QUERY)
        If h = 0 Then Exit Sub
        VFW.ICClose(h)

        BuildName = CStr(RegistryHelp.CurrentUser.GetValue(RegistryKey, Nothing))

        If BuildName Is Nothing Then
            Exit Sub
        End If

        If Not RegFirstPass.ContainsKey(BuildName) Then
            RegFirstPass.Clear()
            RegSecondPass.Clear()
            RegCompCheck.Clear()

            SetRegList(BuildName, "-bvn1 780000 -vbv 4854000,3145728,2359296 -dir """ + dir + """ -b 1 -nf -profile=3", VirtualDubEncoder.Modes.First)
            SetRegList(BuildName, "-bvnn 780000 -vbv 4854000,3145728,2359296 -dir """ + dir + """ -b 1 -nf -profile=3", VirtualDubEncoder.Modes.Second)
            SetRegList(BuildName, "-b1q 2 -dir """ + dir + """ -b 1 -nf -vbv_bitrate=27336400 -vbv_size=100663296 -vbv_occupancy=75497472", VirtualDubEncoder.Modes.CompCheck)
        End If

        If QualityMode Then
            If Not RegSecondPass(BuildName).ToString.Contains("-bv1q") Then
                RegSecondPass(BuildName) = "-bv1q 3 -vbv 4854000,3145728,2359296 -dir """ + dir + """ -b 1 -nf -profile=3"
            End If
        ElseIf Passes > 1 Then
            If Not RegSecondPass(BuildName).ToString.Contains("-bvnn") Then
                RegSecondPass(BuildName) = "-bvnn 780000 -vbv 4854000,3145728,2359296 -dir """ + dir + """ -b 1 -nf -profile=3"
            End If
        End If

        If Not RegCompCheck(BuildName).ToString.Contains("-b1q 2") Then
            RegCompCheck(BuildName) = "-b1q 2 -dir """ + dir + """ -b 1 -nf -vbv_bitrate=27336400 -vbv_size=100663296 -vbv_occupancy=75497472"
        End If
    End Sub

    Public Overrides Sub ModifyValues(ByVal sl As SortedList)
        Verify()
        Dim value As String = sl(BuildName).ToString
        Dim bitrate As New Regex("(-bvn\w) \d+")

        If bitrate.IsMatch(value) Then
            sl(BuildName) = bitrate.Replace(value, "$1 " + (p.VideoBitrate * 1000).ToString)
        End If
    End Sub

    Protected Overrides Function VerifyRequirements() As Boolean
        If Not Paths.VerifyRequirements Then
            Return False
        End If

        If Not Paths.DivX.VerifyOK(False) Then
            Return False
        End If

        If UseVirtualDub Then
            If Not Paths.VirtualDub.VerifyOK(False) Then
                Return False
            End If
        Else
            If Not Paths.VirtualDubMod.VerifyOK(False) Then
                Return False
            End If
        End If

        Return True
    End Function
End Class

<Serializable()> _
Public Class CLIEncoder
    Inherits VideoEncoder

    Public Sub New(ByVal streamType As StreamType)
        MyBase.New("Command Line", "Command Line Encoder")
        Muxer = New NullMuxer
        Me.OutputStreamType = streamType
        IsCompCheckEnabledValue = True
    End Sub

    Private CommandLinesValue As String = ""

    Public Property CommandLines() As String
        Get
            Return CommandLinesValue
        End Get
        Set(ByVal Value As String)
            CommandLinesValue = Value
        End Set
    End Property

    Private CompCheckCommandLinesValue As String

    Public Property CompCheckCommandLines() As String
        Get
            Return CompCheckCommandLinesValue
        End Get
        Set(ByVal Value As String)
            CompCheckCommandLinesValue = Value
        End Set
    End Property

    Private ParameterFileValue As String

    Public Property ParameterFile() As String
        Get
            Return ParameterFileValue
        End Get
        Set(ByVal Value As String)
            ParameterFileValue = Value
        End Set
    End Property

    Public Overrides Sub Encode()
        For Each i As String In StringHelp.SplitLines(Macro.Solve(CommandLines))
            Log.WriteHeader("Video Encoding")
            Log.WriteLine("Encoder Type: " + TypeName)

            Dim startTime As DateTime = DateTime.Now

            Dim pw As New ProcessWrapper

            ProcessForm.ProcessWrapper = pw
            p.TargetAVSDoc.Synchronize()

            pw.CommandLine = i

            Log.WriteLine("Command Line: " + i)

            pw.Minimized = s.RunAppsMinimized.Value
            pw.Wait = True
            pw.Priority = s.ProcessPriority.Value
            pw.Start()

            Log.WriteHeader("Video Encoding Statistics")
            Log.WriteStats(startTime, p.TargetAVSDoc.GetFrames)
        Next
    End Sub

    Private Sub ShowConfigDialog()
        Using f As New CmdlEncoderForm(Me)
            f.ShowDialog()
        End Using

        OnStateChange()
    End Sub

    Public Overrides Function GetMenu() As List(Of OptionListBoxItem)
        Dim ret As New List(Of OptionListBoxItem)

        Dim configuration As New OptionListBoxItem
        configuration.Text = "Codec Configuration"
        configuration.Description = "Opens the codec configuration dialog."
        configuration.ClickSub = AddressOf ShowConfigDialog
        ret.Add(configuration)

        If IsCompCheckEnabled Then
            Dim startCompCheckDialog As New OptionListBoxItem
            startCompCheckDialog.Text = "Run Compressibility Check"
            startCompCheckDialog.Description = "Runs the compressibility check. The compressibility check helps to find a optimal bitrate."
            startCompCheckDialog.ClickSub = AddressOf StartCompCheck
            ret.Add(startCompCheckDialog)
        End If

        Dim muxConfig As New OptionListBoxItem
        muxConfig.Text = "Container Configuration"
        muxConfig.Description = "Opens the container configuration dialog."
        muxConfig.ClickSub = AddressOf OpenMuxerConfigDialog
        ret.Add(muxConfig)

        Return ret
    End Function

    Public Overrides Sub StartCompCheck()
        If Not Paths.VerifyRequirements Then Exit Sub
        If Not g.IsValidSource Then Exit Sub

        ProcessForm.ShowForm(False)
        Log.WriteHeader("Compressibility Check")

        Dim doc As New AviSynthDocument

        For Each i As AviSynthFilter In p.TargetAVSDoc.Filters
            doc.Filters.Add(i.GetCopy)
        Next

        doc.Filters.Add(New AviSynthFilter("SelectRangeEvery", "SelectRangeEvery", "SelectRangeEvery(" + ((100 \ p.CompCheckRange.Value) * 14).ToString + ",14)", True))
        doc.Path = Paths.GetTempDir() + p.Name + "_CompCheck.avs"
        doc.Synchronize()

        For Each i As String In StringHelp.SplitLines(Macro.Solve(CompCheckCommandLines))
            Dim pw As New ProcessWrapper

            ProcessForm.ProcessWrapper = pw

            pw.CommandLine = i

            Log.WriteLine("Command Line: " + pw.CommandLine)

            pw.Minimized = s.RunAppsMinimized.Value
            pw.Wait = True
            pw.Priority = s.ProcessPriority.Value

            Try
                pw.Start()
            Catch ex As AbortException
                ProcessForm.CloseProcessForm()
                Exit Sub
            End Try
        Next

        Dim bits As Long = (New FileInfo(Paths.GetTempDir + p.Name + "_CompCheck" + GetExtension()).Length) * 8
        p.Compressibility = (bits / doc.GetFrames) / (p.TargetWidth * p.TargetHeight)

        OnAfterCompCheck()

        g.MainForm.UpdateControls()
        g.MainForm.Assistant()

        Log.WriteLine(CInt(Calc.GetPercent).ToString() + " %")

        ProcessForm.CloseProcessForm()
    End Sub
End Class

<Serializable()> _
Public Class NullEncoder
    Inherits VideoEncoder

    Public Sub New(ByVal name As String)
        MyBase.New(name, "Null Encoder")
        Muxer = New NullMuxer
        OutputStreamType = StaxRip.StreamType.AVI
        QualityMode = True
    End Sub

    Public Overrides Sub Encode()
    End Sub

    Public Overrides Function GetMenu() As List(Of OptionListBoxItem)
        Dim ret As New List(Of OptionListBoxItem)

        Dim configuration As New OptionListBoxItem
        configuration.Text = "Codec Configuration"
        configuration.Description = "Opens the codec configuration dialog."
        configuration.ClickSub = AddressOf ShowConfigDialog
        ret.Add(configuration)

        Dim muxConfig As New OptionListBoxItem
        muxConfig.Text = "Container Configuration"
        muxConfig.Description = "Opens the container configuration dialog."
        muxConfig.ClickSub = AddressOf OpenMuxerConfigDialog
        ret.Add(muxConfig)

        Return ret
    End Function

    Private Sub ShowConfigDialog()
        Dim streamTypeSetting As New SettingBag(Of StreamType)(OutputStreamType)

        Dim f As New SettingTreeViewForm(Name, "The Null Encoder doesn't perform any encoding but is usefull to remux a project.")
        f.SettingTreeView.AddSetting(New ComboboxTreeNodeSetting(Of StreamType)("Output Type", "General", streamTypeSetting, "Stream type of the output file."))
        f.SettingTreeView.Nodes(0).ExpandAll()

        If f.ShowDialog() = DialogResult.OK Then
            OutputStreamType = streamTypeSetting.Value
        End If

        f.Dispose()
        g.MainForm.Assistant()
    End Sub
End Class

<Serializable()> _
Public Class x264Encoder
    Inherits VideoEncoder

    Public Sub New()
        MyBase.New("x264", "x264 Encoder")
        Muxer = New MP4BoxMuxer
        IsCompCheckEnabledValue = True
    End Sub

    Private ParamsValue As New x264Params

    Public Property Params() As x264Params
        Get
            Return ParamsValue
        End Get
        Set(ByVal Value As x264Params)
            ParamsValue = Value
        End Set
    End Property

    Public Overloads Sub Encode(ByVal passName As String, ByVal args As String)
        Dim startTime As DateTime = DateTime.Now

        Dim pw As New ProcessWrapper
        pw.File = Paths.x264.GetPath(False)
        pw.Arguments = args

        Log.WriteHeader(passName)
        Log.WriteLine("Command Line: " + pw.CommandLine)

        pw.Minimized = s.RunAppsMinimized.Value
        pw.Wait = True
        pw.Priority = s.ProcessPriority.Value

        ProcessForm.ProcessWrapper = pw

        pw.Start()

        If startTime.AddSeconds(5) > DateTime.Now AndAlso pw.Process.ExitCode <> 0 Then
            Dim p As New Process
            p.StartInfo.UseShellExecute = False
            p.StartInfo.RedirectStandardOutput = True
            p.StartInfo.CreateNoWindow = True
            p.StartInfo.FileName = Paths.x264.GetPath(False)
            p.StartInfo.Arguments = args
            p.Start()
            Log.WriteHeader("x264 Error")
            Log.WriteLine(p.StandardOutput.ReadToEnd())
            p.WaitForExit()
        End If

        Log.WriteHeader(passName + " Statistics")
        Log.WriteStats(startTime, p.TargetAVSDoc.GetFrames)
    End Sub

    Public Overrides Sub Encode()
        p.TargetAVSDoc.Synchronize()

        Encode("x264 Single/First Pass Encoding", GetCommandLineArgs(1))

        If Params.Mode.Value = x264Mode.TwoPass OrElse Params.Mode.Value = x264Mode.ThreePass Then
            Encode("Second Pass Encoding", GetCommandLineArgs(2))
        End If

        If Params.Mode.Value = x264Mode.ThreePass Then
            Encode("Third Pass Encoding", GetCommandLineArgs(3))
        End If
    End Sub

    Public Overrides Function GetMenu() As List(Of OptionListBoxItem)
        Dim ret As New List(Of OptionListBoxItem)

        Dim configuration As New OptionListBoxItem
        configuration.Text = "Codec Configuration"
        configuration.Description = "Opens the codec configuration dialog."
        configuration.ClickSub = AddressOf ShowConfigDialog
        ret.Add(configuration)

        If IsCompCheckEnabled Then
            Dim startCompCheckDialog As New OptionListBoxItem
            startCompCheckDialog.Text = "Run Compressibility Check"
            startCompCheckDialog.Description = "Runs the compressibility check. The compressibility check helps to find a optimal bitrate."
            startCompCheckDialog.ClickSub = AddressOf StartCompCheck
            ret.Add(startCompCheckDialog)
        End If

        Dim muxConfig As New OptionListBoxItem
        muxConfig.Text = "Container Configuration"
        muxConfig.Description = "Opens the container configuration dialog."
        muxConfig.ClickSub = AddressOf OpenMuxerConfigDialog
        ret.Add(muxConfig)

        Return ret
    End Function

    Private Sub ShowConfigDialog()
        Using f As New x264Form(Me)
            f.ShowDialog()
        End Using

        OnStateChange()
    End Sub

    Public Function GetCommandLineArgs(ByVal pass As Integer) As String
        Return GetCommandLineArgs(pass, p.TargetAVSDoc.Path, Filepath.GetDirAndNameNoExt(OutputPath) + GetExtension())
    End Function

    Private Function IsTurboPass(ByVal pass As Integer) As Boolean
        If Params.Mode.Value = x264Mode.TwoPass AndAlso pass <> 2 Then
            Return True
        End If

        If Params.Mode.Value = x264Mode.ThreePass AndAlso pass <> 3 Then
            Return True
        End If

        Return False
    End Function

    Public Function GetCommandLineArgs(ByVal pass As Integer, ByVal sourcePath As String, ByVal targetPath As String) As String
        Dim sb As New StringBuilder

        If Params.Mode.Value = x264Mode.TwoPass OrElse Params.Mode.Value = x264Mode.ThreePass Then
            Select Case pass
                Case 1
                    sb.Append(" --pass 1")
                Case 2
                    sb.Append(" --pass 2")
                Case 3
                    sb.Append(" --pass 3")
            End Select
        End If

        If Params.Mode.Value = x264Mode.SingleQuant Then
            sb.Append(" --qp " + Params.Quant.Value.ToString)
        ElseIf Params.Mode.Value = x264Mode.SingleCRF Then
            sb.Append(" --crf " + Params.Quant.Value.ToString)
        Else
            sb.Append(" --bitrate " + p.VideoBitrate.ToString)
        End If

        If Params.Mode.Value = x264Mode.TwoPass OrElse Params.Mode.Value = x264Mode.ThreePass Then
            sb.Append(" --stats """ + Paths.GetTempDir + p.Name + ".stats""")
        End If

        If Params.GOPSizeMax.Value <> 250 Then
            sb.Append(" --keyint " + Params.GOPSizeMax.Value.ToString)
        End If

        If Params.GOPSizeMin.Value <> 25 Then
            sb.Append(" --min-keyint " + Params.GOPSizeMin.Value.ToString)
        End If

        If Params.ReferenceFrames.Value <> 1 Then
            sb.Append(" --ref " + Params.ReferenceFrames.Value.ToString)
        End If

        If Params.BFrames.Value <> 0 Then
            sb.Append(" --bframes " + Params.BFrames.Value.ToString)

            If Not Params.BFramesAdaptive.Value Then
                sb.Append(" --no-b-adapt")
            End If

            If Params.BFramesPyramid.Value Then
                sb.Append(" --b-pyramid")
            End If

            If Params.BFramesWeightedPrediction.Value Then
                sb.Append(" --weightb")
            End If

            If Params.BFramesBias.Value <> 0 Then
                sb.Append(" --b-bias " + Params.BFramesBias.Value.ToString)
            End If

            If Params.BFramesRDO.Value Then
                sb.Append(" --b-rdo")
            End If
        End If

        If Not Params.LoopFilter.Value Then
            sb.Append(" --nf")
        Else
            If Params.DeblockAlpha.Value <> 0 OrElse Params.DeblockBeta.Value <> 0 Then
                sb.Append(" --filter " + Params.DeblockAlpha.Value.ToString + ":" + Params.DeblockBeta.Value.ToString)
            End If
        End If

        If Not Params.CABAC.Value Then
            sb.Append(" --no-cabac")
        End If

        Dim l As New List(Of String)

        If Params.P8x8.Value Then
            l.Add("p8x8")
        End If

        If Params.B8x8.Value Then
            l.Add("b8x8")
        End If

        If Params.I4x4.Value Then
            l.Add("i4x4")
        End If

        If Params.P4x4.Value Then
            l.Add("p4x4")
        End If

        If Params.I8x8.Value Then
            l.Add("i8x8")
        End If

        If l.Count = 0 Then
            sb.Append(" --analyse none")
        ElseIf l.Count = 5 Then
            sb.Append(" --analyse all")
        Else
            sb.Append(" --analyse " + String.Join(",", l.ToArray))
        End If

        If Params.AdaptiveDCT.Value Then
            sb.Append(" --8x8dct")
        End If

        If Params.SubME.Value <> 5 Then
            sb.Append(" --subme " + Params.SubME.Value.ToString)
        End If

        If Params.MEMethod.Value <> MEMethodMode.hex Then
            sb.Append(" --me " + CType(Params.MEMethod.Value, MEMethodMode).ToString)
        End If

        If Params.Trellis.Value <> 0 Then
            sb.Append(" --trellis " + Params.Trellis.Value.ToString)
        End If

        If Params.MixedRefs.Value Then
            sb.Append(" --mixed-refs")
        End If

        If Params.SceneCut.Value <> 40 Then
            sb.Append(" --scenecut " + Params.SceneCut.Value.ToString)
        End If

        If Params.Progress.Value Then
            sb.Append(" --progress")
        End If

        If Params.Threads.Value > 1 Then
            sb.Append(" --threads " + Params.Threads.Value.ToString)
        End If

        If ARCalc.IsARSignalingRequired Then
            sb.Append(" --sar " + ARCalc.GetPARForY100.ToString + ":100")
        End If

        If Params.NoPSNR.Value Then
            sb.Append(" --no-psnr")
        End If

        If Params.AddAll.Value <> "" Then
            sb.Append(" " + Params.AddAll.Value)
        End If

        Dim ret As String = sb.ToString

        If IsTurboPass(pass) Then
            Dim remove As String = Regex.Replace(Params.TurboRemove.Value, "^\s+|\s+$", "")
            Dim switches As String() = StringHelp.Split(Params.TurboRemove.Value, " ")

            For Each i As String In switches
                Dim re As New Regex(" *" + i + ".*?(?= --)| *" + i + ".*")

                If re.IsMatch(ret) Then
                    ret = re.Replace(ret, "", RegexOptions.IgnoreCase)
                End If
            Next

            If Params.TurboAdd.Value <> "" Then
                ret += " " + Params.TurboAdd.Value
            End If
        End If

        If (Params.Mode.Value = x264Mode.ThreePass AndAlso (pass = 1 OrElse pass = 2)) OrElse Params.Mode.Value = x264Mode.TwoPass AndAlso pass = 1 Then
            ret += " --output NUL """ + sourcePath + """"
        Else
            ret += " --output """ + targetPath + """ """ + sourcePath + """"
        End If

        Return ret.Trim
    End Function

    Public Overrides Property OutputStreamType() As StreamType
        Get
            Select Case Params.OutputType.Value
                Case x264OutputType.MP4
                    Return StaxRip.StreamType.MP4
                Case x264OutputType.RAW
                    Return StaxRip.StreamType.RAW264
                Case x264OutputType.MKV
                    Return StaxRip.StreamType.MKV
            End Select

            Throw New Exception
        End Get
        Set(ByVal value As StreamType)
            Throw New Exception
        End Set
    End Property

    Public Overrides Sub StartCompCheck()
        If Not Paths.VerifyRequirements Then Exit Sub
        If Not g.IsValidSource Then Exit Sub

        ProcessForm.ShowForm(False)
        Log.WriteHeader("Compressibility Check")

        Dim avsPath As String = Paths.GetTempDir() + p.Name + "_CompCheck.avs"
        Dim script As String = Macro.Solve(p.TargetAVSDoc.GetScript) + vbCrLf

        script += "SelectRangeEvery(" + ((100 \ p.CompCheckRange.Value) * 14).ToString + ",14)" + vbCrLf

        StringHelp.WriteFile(avsPath, script)

        Dim pw As New ProcessWrapper

        pw.File = Paths.x264.GetPath(False)

        Dim enc As New x264Encoder
        enc.Params = DirectCast(ObjectHelp.GetCopy(Params), x264Params)
        enc.Params.Mode.Value = x264Mode.SingleCRF
        enc.Params.Quant.Value = 18

        pw.Arguments = enc.GetCommandLineArgs(0, avsPath, Paths.GetTempDir + p.Name + "_CompCheck" + GetExtension())

        Log.WriteLine("Command Line: " + pw.CommandLine)

        pw.Minimized = s.RunAppsMinimized.Value
        pw.Wait = True
        pw.Priority = s.ProcessPriority.Value

        ProcessForm.ProcessWrapper = pw

        Try
            pw.Start()
        Catch ex As AbortException
            ProcessForm.CloseProcessForm()
            Exit Sub
        End Try

        Dim bits As Long = (New FileInfo(Paths.GetTempDir + p.Name + "_CompCheck" + GetExtension()).Length) * 8
        Dim af As New AVIFile

        af.Open(avsPath)
        p.Compressibility = (bits / af.FrameCount) / (p.TargetWidth * p.TargetHeight)
        af.Close()

        OnAfterCompCheck()

        g.MainForm.UpdateControls()
        g.MainForm.Assistant()

        Log.WriteLine(CInt(Calc.GetPercent).ToString() + " %")

        ProcessForm.CloseProcessForm()
    End Sub

    Public Overrides Property QualityMode() As Boolean
        Get
            Return Params.Mode.Value = x264Mode.SingleQuant OrElse Params.Mode.Value = x264Mode.SingleCRF
        End Get
        Set(ByVal Value As Boolean)
            Throw New Exception
        End Set
    End Property
End Class