/* x264Panel.cs $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ using System; using System.Windows.Forms; namespace Handbrake.Controls { public partial class x264Panel : UserControl { /* * TODO This code was ported from the obj-c MacGUI code. It's really messy and could really do with being cleaned up * at some point. */ /// /// Initializes a new instance of the x264 panel user control /// public x264Panel() { InitializeComponent(); if (Properties.Settings.Default.tooltipEnable) ToolTip.Active = true; Reset2Defaults(); } /// /// Gets or sets the X264 query string /// public string X264Query { get { return rtf_x264Query.Text; } set { rtf_x264Query.Text = value; } } /// /// Reset all components to defaults and clears the x264 rtf box /// public void Reset2Defaults() { check_8x8DCT.CheckState = CheckState.Checked; check_Cabac.CheckState = CheckState.Checked; check_mixedReferences.CheckState = CheckState.Checked; check_noDCTDecimate.CheckState = CheckState.Unchecked; check_noFastPSkip.CheckState = CheckState.Unchecked; check_pyrmidalBFrames.CheckState = CheckState.Unchecked; check_weightedBFrames.CheckState = CheckState.Checked; drop_analysis.SelectedIndex = 0; drop_bFrames.SelectedIndex = 0; drop_deblockAlpha.SelectedIndex = 0; drop_deblockBeta.SelectedIndex = 0; drop_directPrediction.SelectedIndex = 0; drop_MotionEstimationMethod.SelectedIndex = 0; drop_MotionEstimationRange.SelectedIndex = 0; drop_refFrames.SelectedIndex = 0; drop_subpixelMotionEstimation.SelectedIndex = 0; drop_trellis.SelectedIndex = 0; slider_psyrd.Value = 10; slider_psytrellis.Value = 0; drop_adaptBFrames.SelectedIndex = 0; rtf_x264Query.Text = ""; } /// /// Iterate over every x264 option, standardize it, write the full string to the x264 rtf box /// public void X264_StandardizeOptString() { /* Set widgets depending on the opt string in field */ String thisOpt; // The separated option such as "bframes=3" String optName; // The option name such as "bframes" String optValue;// The option value such as "3" String changedOptString = ""; String[] currentOptsArray; /*First, we get an opt string to process */ String currentOptString = rtf_x264Query.Text; /*verify there is an opt string to process */ if (currentOptString.Contains("=")) { /*Put individual options into an array based on the ":" separator for processing, result is "="*/ currentOptsArray = currentOptString.Split(':'); /*iterate through the array and get and /// Take a single option and standardize it. Returns as a String /// Input: String. - Single X264 Option. Name only /// Output: String - Single X264 Option. Name only. Changed to standard format /// /// /// private static string X264_StandardizeOptNames(String cleanOptNameString) { String input = cleanOptNameString; if (input.Equals("ref") || input.Equals("frameref")) cleanOptNameString = "ref"; /*No Fast PSkip nofast_pskip*/ if (input.Equals("no-fast-pskip") || input.Equals("no_fast_pskip") || input.Equals("nofast_pskip")) cleanOptNameString = "no-fast-pskip"; /*No Dict Decimate*/ if (input.Equals("no-dct-decimate") || input.Equals("no_dct_decimate") || input.Equals("nodct_decimate")) cleanOptNameString = "no-dct-decimate"; /*Subme*/ if (input.Equals("subme")) cleanOptNameString = "subq"; /*ME Range*/ if (input.Equals("me-range") || input.Equals("me_range")) cleanOptNameString = "merange"; /*WeightB*/ if (input.Equals("weight-b") || input.Equals("weight_b")) cleanOptNameString = "weightb"; /*B Pyramid*/ if (input.Equals("b_pyramid")) cleanOptNameString = "b-pyramid"; /*Direct Prediction*/ if (input.Equals("direct-pred") || input.Equals("direct_pred")) cleanOptNameString = "direct"; /*Deblocking*/ if (input.Equals("filter")) cleanOptNameString = "deblock"; /*Analysis*/ if (input.Equals("partitions")) cleanOptNameString = "analyse"; return cleanOptNameString; } /// /// Resets the GUI widgets to the contents of the option string. /// public void X264_SetCurrentSettingsInPanel() { /* Set widgets depending on the opt string in field */ String thisOpt; // The separated option such as "bframes=3" String optName; // The option name such as "bframes" String optValue;// The option value such as "3" String[] currentOptsArray; //Set currentOptString to the contents of the text box. String currentOptString = rtf_x264Query.Text.Replace("\n", ""); /*verify there is an opt string to process */ if (currentOptString.Contains("=")) { /*Put individual options into an array based on the ":" separator for processing, result is "="*/ currentOptsArray = currentOptString.Split(':'); /*iterate through the array and get and and /// This function will update the X264 Query when one of the GUI widgets changes. /// private void OnX264WidgetChange(string sender) { Animate(sender); String optNameToChange = sender; String currentOptString = rtf_x264Query.Text; /*First, we create a pattern to check for ":"optNameToChange"=" to modify the option if the name falls after the first character of the opt string (hence the ":") */ String checkOptNameToChange = ":" + optNameToChange + "="; String checkOptNameToChangeBegin = optNameToChange + "="; // IF the current H264 Option String Contains Multiple Items or Just 1 Item if ((currentOptString.Contains(checkOptNameToChange)) || (currentOptString.StartsWith(checkOptNameToChangeBegin))) HasOptions(currentOptString, optNameToChange); else // IF there is no options in the rich text box! HasNoOptions(optNameToChange); } /// /// Called when the current x264 option string contains multiple (or a single) item(s) in it seperated by : /// it updates the current option that the widget corrosponds to, if it is already in thes string. /// /// /// private void HasOptions(string currentOptString, string optNameToChange) { String thisOpt; // The separated option such as "bframes=3" String optName; // The option name such as "bframes" String[] currentOptsArray; /* Create new empty opt string*/ String changedOptString = ""; /*Put individual options into an array based on the ":" separator for processing, result is "="*/ currentOptsArray = currentOptString.Split(':'); /*iterate through the array and get and /// Add's an option to the x264 query string. /// Handles 2 cases. 1 Where rtf_x264Query.Text is empty, and one where there is an option with no value, /// e.g no-fast-pskip /// /// private void HasNoOptions(IEquatable optNameToChange) { string colon = ""; if (rtf_x264Query.Text != "") colon = ":"; string query = rtf_x264Query.Text; if (optNameToChange.Equals("me")) { switch (drop_MotionEstimationMethod.SelectedIndex) { case 1: query = query + colon + "me=dia"; break; case 2: query = query + colon + "me=hex"; break; case 3: query = query + colon + "me=umh"; break; case 4: query = query + colon + "me=esa"; break; case 5: query = query + colon + "me=tesa"; break; default: break; } } else if (optNameToChange.Equals("direct")) { switch (drop_directPrediction.SelectedIndex) { case 1: query = query + colon + "direct=none"; break; case 2: query = query + colon + "direct=spatial"; break; case 3: query = query + colon + "direct=temporal"; break; case 4: query = query + colon + "direct=auto"; break; default: break; } } else if (optNameToChange.Equals("analyse")) { switch (drop_analysis.SelectedIndex) { case 1: query = query + colon + "analyse=none"; break; case 2: query = query + colon + "analyse=all"; break; default: break; } } else if (optNameToChange.Equals("merange")) { int value = drop_MotionEstimationRange.SelectedIndex + 3; query = query + colon + "merange=" + value; } else if (optNameToChange.Equals("b-adapt")) { int value = drop_adaptBFrames.SelectedIndex - 1; query = query + colon + "b-adapt=" + value; } else if (optNameToChange.Equals("deblock")) { String da = drop_deblockAlpha.SelectedItem.ToString(); String db = drop_deblockBeta.Text; if (((da.Contains("Default")) && (db.Contains("Default"))) || ((da.Contains("0")) && (db.Contains("0")))) { drop_deblockBeta.SelectedItem = "Default (0)"; drop_deblockAlpha.SelectedItem = "Default (0)"; } else { if (db.Contains("Default")) db = "0"; if (da.Contains("Default")) da = "0"; query = query + colon + "deblock=" + da + "," + db; } } else if (optNameToChange.Equals("psy-rd")) { if (slider_psyrd.Value == 10 && slider_psytrellis.Value == 0) query += ""; else { double psyrd = slider_psyrd.Value * 0.1; double psytre = slider_psytrellis.Value * 0.1; string rd = psyrd.ToString("f1"); string rt = psytre.ToString("f1"); query += colon + "psy-rd=" + rd + "," + rt; } } else if (optNameToChange.Equals("mixed-refs")) { if (check_mixedReferences.CheckState == CheckState.Checked) query = query + colon + "mixed-refs=1"; else query = query + colon + "mixed-refs=0"; } else if (optNameToChange.Equals("weightb")) { if (check_weightedBFrames.CheckState != CheckState.Checked) query = query + colon + "weightb=0"; } else if (optNameToChange.Equals("b-pyramid")) { if (check_pyrmidalBFrames.CheckState == CheckState.Checked) query = query + colon + "b-pyramid=1"; } else if (optNameToChange.Equals("no-fast-pskip")) { if (check_noFastPSkip.CheckState == CheckState.Checked) query = query + colon + "no-fast-pskip=1"; } else if (optNameToChange.Equals("no-dct-decimate")) { if (check_noDCTDecimate.CheckState == CheckState.Checked) query = query + colon + "no-dct-decimate=1"; } else if (optNameToChange.Equals("8x8dct")) { if (check_8x8DCT.CheckState == CheckState.Checked) query = query + colon + "8x8dct=1"; } else if (optNameToChange.Equals("cabac")) { if (check_Cabac.CheckState != CheckState.Checked) query = query + colon + "cabac=0"; } else if (optNameToChange.Equals("ref")) { if (!drop_refFrames.SelectedItem.ToString().Contains("Default")) query = query + colon + "ref=" + drop_refFrames.SelectedItem; } else if (optNameToChange.Equals("bframes")) { String value = drop_bFrames.SelectedItem.ToString(); if (!drop_bFrames.SelectedItem.ToString().Contains("Default")) query = query + colon + "bframes=" + value; } else if (optNameToChange.Equals("subq")) { String value = drop_subpixelMotionEstimation.SelectedItem.ToString(); if (!drop_subpixelMotionEstimation.SelectedItem.ToString().Contains("Default")) query = query + colon + "subq=" + value; } else if (optNameToChange.Equals("trellis")) { if (!drop_trellis.SelectedItem.ToString().Contains("Default")) query = query + colon + "trellis=" + drop_trellis.SelectedItem; } rtf_x264Query.Text = query; } /// /// Shows and hides controls based on the values of other controls. /// /// private void Animate(string sender) { /* Lots of situations to cover. - B-frames (when 0 turn of b-frame specific stuff, when < 2 disable b-pyramid) - CABAC (when 0 turn off trellis) - analysis (if none, turn off 8x8dct) - refs (under 2, disable mixed-refs) - subme (if under 6, turn off psy-rd and psy-trel) - trellis (if 0, turn off psy-trel) */ switch(sender) { case "bframes": if (drop_bFrames.SelectedIndex >0 && drop_bFrames.SelectedIndex < 2 ) { /* If the b-frame widget is at 0 or 1, the user has chosen not to use b-frames at all. So disable the options that can only be used when b-frames are enabled. */ check_weightedBFrames.Visible = false; check_pyrmidalBFrames.Visible = false; drop_directPrediction.Visible = false; lbl_direct_prediction.Visible = false; check_weightedBFrames.CheckState = CheckState.Unchecked; check_pyrmidalBFrames.CheckState = CheckState.Unchecked; drop_directPrediction.SelectedIndex = 0; drop_adaptBFrames.Visible = false; lbl_adaptBFrames.Visible = false; drop_adaptBFrames.SelectedIndex = 0; } else if (drop_bFrames.SelectedIndex == 2) { /* Only 1 b-frame? Disable b-pyramid. */ check_pyrmidalBFrames.Visible = false; check_pyrmidalBFrames.CheckState = CheckState.Unchecked; check_weightedBFrames.Visible = true; drop_directPrediction.Visible = true; lbl_direct_prediction.Visible = true; drop_adaptBFrames.Visible = true; lbl_adaptBFrames.Visible = true; } else { check_weightedBFrames.Visible = true; check_pyrmidalBFrames.Visible = true; drop_directPrediction.Visible = true; lbl_direct_prediction.Visible = true; drop_adaptBFrames.Visible = true; lbl_adaptBFrames.Visible = true; } break; case "cabac": if (check_Cabac.Checked == false) { /* Without CABAC entropy coding, trellis doesn't run. */ drop_trellis.Visible = false; drop_trellis.SelectedIndex = 0; lbl_trellis.Visible = false; } else { drop_trellis.Visible = true; lbl_trellis.Visible = true; } break; case "analyse": if (drop_analysis.SelectedIndex == 1) { /* No analysis? Disable 8x8dct */ check_8x8DCT.Visible = false; if (sender != "8x8dct") check_8x8DCT.CheckState = CheckState.Unchecked; } else check_8x8DCT.Visible = true; break; case "ref": if (drop_refFrames.SelectedIndex > 0 && drop_refFrames.SelectedIndex < 3) { check_mixedReferences.Visible = false; if (sender != "mixed-refs") check_mixedReferences.CheckState = CheckState.Unchecked; } else check_mixedReferences.Visible = true; break; case "me": // Motion Estimation if (drop_MotionEstimationMethod.SelectedIndex < 3) { drop_MotionEstimationRange.Visible = false; lbl_merange.Visible = false; drop_MotionEstimationRange.SelectedIndex = 0; } else { drop_MotionEstimationRange.Visible = true; lbl_merange.Visible = true; } break; case "subq": // subme if (drop_subpixelMotionEstimation.SelectedIndex != 0 && drop_subpixelMotionEstimation.SelectedIndex < 7) { slider_psyrd.Visible = false; slider_psyrd.Value = 10; lbl_psyrd.Visible = false; slider_psytrellis.Visible = false; slider_psytrellis.Value = 0; lbl_psytrellis.Visible = false; } else { slider_psyrd.Visible = true; lbl_psyrd.Visible = true; if (drop_trellis.SelectedIndex >= 2 && check_Cabac.Checked && slider_psytrellis.Visible == false) { slider_psytrellis.Visible = true; lbl_psytrellis.Visible = true; } } break; case "trellis": // subme if (drop_trellis.SelectedIndex > 0 && drop_trellis.SelectedIndex < 2 ) { slider_psytrellis.Visible = false; slider_psytrellis.Value = 0; lbl_psytrellis.Visible = false; } else { if ((drop_subpixelMotionEstimation.SelectedIndex == 0 || drop_subpixelMotionEstimation.SelectedIndex >= 7) && check_Cabac.Checked && slider_psytrellis.Visible == false) { slider_psytrellis.Visible = true; lbl_psytrellis.Visible = true; } } break; } } private void widgetControlChanged(object sender, EventArgs e) { Control changedControlName = (Control)sender; string controlName = ""; switch (changedControlName.Name.Trim()) { case "drop_refFrames": controlName = "ref"; break; case "check_mixedReferences": controlName = "mixed-refs"; break; case "drop_bFrames": controlName = "bframes"; break; case "drop_directPrediction": controlName = "direct"; break; case "check_weightedBFrames": controlName = "weightb"; break; case "check_pyrmidalBFrames": controlName = "b-pyramid"; break; case "drop_MotionEstimationMethod": controlName = "me"; break; case "drop_MotionEstimationRange": controlName = "merange"; break; case "drop_subpixelMotionEstimation": controlName = "subq"; break; case "drop_analysis": controlName = "analyse"; break; case "check_8x8DCT": controlName = "8x8dct"; break; case "drop_deblockAlpha": controlName = "deblock"; break; case "drop_deblockBeta": controlName = "deblock"; break; case "drop_trellis": controlName = "trellis"; break; case "check_noFastPSkip": controlName = "no-fast-pskip"; break; case "check_noDCTDecimate": controlName = "no-dct-decimate"; break; case "check_Cabac": controlName = "cabac"; break; case "slider_psyrd": controlName = "psy-rd"; break; case "slider_psytrellis": controlName = "psy-rd"; break; case "drop_adaptBFrames": controlName = "b-adapt"; break; } OnX264WidgetChange(controlName); } private void rtf_x264Query_TextChanged(object sender, EventArgs e) { if (rtf_x264Query.Text.EndsWith("\n")) { string query = rtf_x264Query.Text.Replace("\n", ""); Reset2Defaults(); rtf_x264Query.Text = query; X264_StandardizeOptString(); X264_SetCurrentSettingsInPanel(); if (rtf_x264Query.Text == string.Empty) Reset2Defaults(); } } private void btn_reset_Click(object sender, EventArgs e) { rtf_x264Query.Text = ""; Reset2Defaults(); } } }