OSDN Git Service

LinGui: change how x264 options are handled
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 7 Aug 2008 17:43:55 +0000 (17:43 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 7 Aug 2008 17:43:55 +0000 (17:43 +0000)
- there is now one preset key that contains the option string
- options displayed in widgets and entry box stay reflect each other
- enlarged the entry box so all options can be seen

git-svn-id: svn://localhost/HandBrake/trunk@1614 b64f7644-9d1e-0410-96f1-a4d463321fa5

gtk/src/callbacks.c
gtk/src/ghb.ui
gtk/src/hb-backend.c
gtk/src/internal_defaults
gtk/src/internal_defaults.h
gtk/src/main.c
gtk/src/settings.c
gtk/src/settings.h
gtk/src/standard_presets

index 78196b2..8c1088f 100644 (file)
@@ -70,7 +70,6 @@ static dependency_t dep_map[] =
        {"vquality_type_target", "video_target_size", "enable", FALSE},
        {"vquality_type_constant", "video_quality", "enable", FALSE},
        {"vquality_type_constant", "constant_rate_factor", "enable", FALSE},
-       {"vquality_type_constant", "x264_trellis", "enable", TRUE},
        {"vquality_type_constant", "two_pass", "enable", TRUE},
        {"vquality_type_constant", "turbo", "enable", TRUE},
        {"two_pass", "turbo", "enable", FALSE},
@@ -131,7 +130,6 @@ dep_check(signal_user_data_t *ud, const gchar *name)
 {
        GtkWidget *widget;
        GObject *dep_object;
-       gchar *value;
        int ii;
        int count = sizeof(dep_map) / sizeof(dependency_t);
        gboolean result = TRUE;
@@ -143,17 +141,22 @@ dep_check(signal_user_data_t *ud, const gchar *name)
                {
                        widget = GHB_WIDGET(ud->builder, dep_map[ii].widget_name);
                        dep_object = gtk_builder_get_object(ud->builder, dep_map[ii].dep_name);
-                       value = ghb_widget_short_opt(widget);
-                       if (dep_object == NULL || widget == NULL)
+                       if (dep_object == NULL)
                        {
                                g_message("Failed to find widget\n");
                        }
                        else
                        {
+                               gchar *value;
                                gint jj = 0;
                                gchar **values = g_strsplit(dep_map[ii].enable_value, "|", 10);
                                gboolean sensitive = FALSE;
 
+                               if (widget)
+                                       value = ghb_widget_short_opt(widget);
+                               else
+                                       value = g_strdup( ghb_settings_get_short_opt(
+                                               ud->settings, dep_map[ii].widget_name));
                                while (values && values[jj])
                                {
                                        if (values[jj][0] == '>')
@@ -186,8 +189,8 @@ dep_check(signal_user_data_t *ud, const gchar *name)
                                sensitive = dep_map[ii].disable_if_equal ^ sensitive;
                                if (!sensitive) result = FALSE;
                                g_strfreev (values);
+                               g_free(value);
                        }
-                       g_free(value);
                }
        }
        return result;
@@ -1476,6 +1479,59 @@ generic_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
        return FALSE;
 }
 
+// Flag needed to prevent x264 options processing from chasing its tail
+static gboolean ignore_options_update = FALSE;
+
+void
+x264_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+       ghb_widget_to_setting(ud->settings, widget);
+       if (!ignore_options_update)
+       {
+               ignore_options_update = TRUE;
+               ghb_x264_opt_update(ud, widget);
+               ignore_options_update = FALSE;
+       }
+       check_depencency(ud, widget);
+       clear_presets_selection(ud);
+}
+
+void
+x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+       g_debug("x264_entry_changed_cb ()\n");
+       if (!ignore_options_update)
+       {
+               GtkWidget *textview;
+               textview = GTK_WIDGET(GHB_WIDGET(ud->builder, "x264_options"));
+               ghb_widget_to_setting(ud->settings, textview);
+               const gchar *options;
+               options = ghb_settings_get_string(ud->settings, "x264_options");
+               ignore_options_update = TRUE;
+               ghb_x264_parse_options(ud, options);
+               ignore_options_update = FALSE;
+       }
+}
+
+gboolean
+x264_focus_out_cb(GtkWidget *widget, GdkEventFocus *event, 
+    signal_user_data_t *ud)
+{
+       ghb_widget_to_setting(ud->settings, widget);
+       gchar *options;
+       options = (gchar*)ghb_settings_get_string(ud->settings, "x264_options");
+       options = ghb_sanitize_x264opts(ud, options);
+       ignore_options_update = TRUE;
+       if (options != NULL)
+       {
+               ghb_ui_update(ud, "x264_options", options);
+               ghb_x264_parse_options(ud, options);
+               g_free(options);
+       }
+       ignore_options_update = FALSE;
+       return FALSE;
+}
+
 static void
 clear_audio_list(signal_user_data_t *ud)
 {
index c51e04b..d843529 100644 (file)
                                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                             <property name="tooltip-text" translatable="yes">Selects the number of reference frames that can be used. Slows down encoding.  Good typical values are 3 to 5. Animation can benefit from more (8 to 10).</property>
                                             <property name="adjustment">adjustment8</property>
-                                            <signal handler="setting_widget_changed_cb" name="value_changed"/>
+                                            <signal handler="x264_widget_changed_cb" name="value_changed"/>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
                                         <property name="label" translatable="yes">Mixed References</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
                                         <property name="expand">False</property>
                               <object class="GtkLabel" id="label50">
                                 <property name="visible">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label" translatable="yes">&lt;b&gt;Refernce Frames&lt;/b&gt;</property>
+                                <property name="label" translatable="yes">&lt;b&gt;Reference Frames&lt;/b&gt;</property>
                                 <property name="use_markup">True</property>
                               </object>
                             </child>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">Sane values are 1-6. B-Frames are smaller than other frames, so they let you pack in more quality at the same bitrate. Use more of them with animated material: 9-16.</property>
                                                 <property name="adjustment">adjustment9</property>
-                                                <signal handler="setting_widget_changed_cb" name="value_changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="value_changed"/>
                                               </object>
                                             </child>
                                           </object>
                                                 <property name="visible">True</property>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">This option can improve compression efficiency. </property>
-                                                <signal handler="setting_widget_changed_cb" name="changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="changed"/>
                                               </object>
                                             </child>
                                           </object>
                                         <property name="position">1</property>
                                       </packing>
                                     </child>
+
+                                    <child>
+                                      <object class="GtkTable" id="table8">
+                                        <property name="visible">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="n_rows">2</property>
+                                        <property name="n_columns">2</property>
+
+                                    <child>
+                                      <object class="GtkCheckButton" id="x264_bpyramid">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="tooltip-text" translatable="yes">Allows B-Frames to be used as references for other B-Frames. Improves encoding efficiency with little speed penalty</property>
+                                        <property name="label" translatable="yes">Pyramidal B-Frames</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
+                                      </object>
+                                    </child>
                                     <child>
                                       <object class="GtkCheckButton" id="x264_weighted_bframes">
                                         <property name="visible">True</property>
                                         <property name="label" translatable="yes">Weighted B-Frames</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
-                                        <property name="position">2</property>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
                                       </packing>
                                     </child>
                                     <child>
                                         <property name="tooltip-text" translatable="yes">When B-frame rate distortion optimization is enabled, x264 tries several different methods of compression for each part of a frame, and chooses the one that looks the best. You need to use a subpixel motion estimation refinement level of 6 or 7 for this to work.</property>
                                         <property name="label" translatable="yes">B-Frame Rate Distortion</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
-                                        <property name="position">3</property>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
                                       </packing>
                                     </child>
                                     <child>
                                         <property name="label" translatable="yes">Bidirectional Refinement</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
-                                        <property name="position">4</property>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
                                       </packing>
                                     </child>
-                                    <child>
-                                      <object class="GtkCheckButton" id="x264_bpyramid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                        <property name="tooltip-text" translatable="yes">Allows B-Frames to be used as references for other B-Frames. Improves encoding efficiency with little speed penalty</property>
-                                        <property name="label" translatable="yes">Pyramidal B-Frames</property>
-                                        <property name="active">True</property>
-                                        <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+
                                       </object>
                                       <packing>
-                                        <property name="position">5</property>
+                                        <property name="position">2</property>
                                       </packing>
                                     </child>
+
                                   </object>
                                 </child>
                               </object>
                                 <property name="left_padding">12</property>
                                 <property name="right_padding">2</property>
                                 <child>
-                                  <object class="GtkEntry" id="x264_options">
+                                  <object class="GtkTextView" id="x264_options">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="tooltip-text" translatable="yes">Enter x264 options here that are not otherwise available</property>
-                                    <property name="truncate_multiline">True</property>
-                                    <signal handler="generic_entry_changed_cb" name="changed"/>
-                                    <signal handler="generic_focus_out_cb" name="focus_out_event"/>
+                                        <property name="tooltip-text" translatable="yes">Your selected options will appear here. 
+You can edit these and add additional options.  
+
+Default values will not be shown. The defaults are:
+ref=1:mixed-refs=0:bframes=0:direct=spatial:b-pyramid=0:
+weightb=0:brdo=0:bime=0:me=hex:merange=16:subme=5:
+analyse=some:8x8dct=0:deblock=0,0:trellis=0:
+no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
+                                    <property name="wrap_mode">GTK_WRAP_CHAR</property>
+                                    <property name="accepts_tab">False</property>
+                                    <signal handler="x264_focus_out_cb" name="focus_out_event"/>
                                   </object>
                                 </child>
                               </object>
                             </child>
                           </object>
                           <packing>
-                            <property name="expand">False</property>
+                            <property name="expand">True</property>
                             <property name="padding">2</property>
                             <property name="position">2</property>
                           </packing>
                         </child>
                       </object>
+                      <packing>
+                        <property name="expand">True</property>
+                      </packing>
                     </child>
                     <child>
                       <object class="GtkVBox" id="vbox25">
                                                 <property name="visible">True</property>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">This sets the shape of the area x264 searches when estimating motion. Your choices are a diamond, a hexagon, a more complex hexagonal shape, or searching the entire frame. You are best off using Uneven Multi-Hexagonal searching.</property>
-                                                <signal handler="setting_widget_changed_cb" name="changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="changed"/>
                                               </object>
                                             </child>
                                           </object>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">This range is the radius, in pixels, x264 should use for motion estimation searches. It only has an effect when you use Uneven Multi-Hexagonal or Exhaustive searching. 24, 32, and 64 are good values.</property>
                                                 <property name="adjustment">adjustment10</property>
-                                                <signal handler="setting_widget_changed_cb" name="value_changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="value_changed"/>
                                               </object>
                                             </child>
                                           </object>
                                                 <property name="visible">True</property>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">Determines how motion estimation decisions are made. 1 is lowest quality and fastest. 7 is highest quality and slowest.  5 or 6 are commonly used values.</property>
-                                                <signal handler="setting_widget_changed_cb" name="changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="changed"/>
                                               </object>
                                             </child>
                                           </object>
                                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                                 <property name="tooltip-text" translatable="yes">Determines which macroblock partitions are analyzed.
 "Some" is p8x8, b8x8, i8x8, i4x4.</property>
-                                                <signal handler="setting_widget_changed_cb" name="changed"/>
+                                                <signal handler="x264_widget_changed_cb" name="changed"/>
                                               </object>
                                             </child>
                                           </object>
                                                 <property name="label" translatable="yes">8x8dct</property>
                                                 <property name="active">True</property>
                                                 <property name="draw_indicator">True</property>
-                                                <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                                <signal handler="x264_widget_changed_cb" name="toggled"/>
                                               </object>
                                             </child>
                                           </object>
                                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                             <property name="tooltip-text" translatable="yes">Deblocking filter. Alpha: determines the strength of the deblocking action.</property>
                                             <property name="adjustment">adjustment11</property>
-                                            <signal handler="setting_widget_changed_cb" name="value_changed"/>
+                                            <signal handler="x264_widget_changed_cb" name="value_changed"/>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
                                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                             <property name="tooltip-text" translatable="yes">Deblocking filter. Beta: determines when something is a block. Higher values increase sensitivity and will flag more blocks.</property>
                                             <property name="adjustment">adjustment12</property>
-                                            <signal handler="setting_widget_changed_cb" name="value_changed"/>
+                                            <signal handler="x264_widget_changed_cb" name="value_changed"/>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
                                             <property name="visible">True</property>
                                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                             <property name="tooltip-text" translatable="yes">Trellis fine-tunes how bitrate is doled out, so it can reduce file size/bitrate or increase quality. "All" forces it to be used more often than "Final Macro Block".</property>
-                                            <signal handler="setting_widget_changed_cb" name="changed"/>
+                                            <signal handler="x264_widget_changed_cb" name="changed"/>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
                                         <property name="label" translatable="yes">No Fast P-Skip</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
                                         <property name="position">2</property>
                                         <property name="label" translatable="yes">No DCT Decimate</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
                                         <property name="position">3</property>
                                         <property name="label" translatable="yes">CABAC Entropy Encoding</property>
                                         <property name="active">True</property>
                                         <property name="draw_indicator">True</property>
-                                        <signal handler="setting_widget_changed_cb" name="toggled"/>
+                                        <signal handler="x264_widget_changed_cb" name="toggled"/>
                                       </object>
                                       <packing>
                                         <property name="position">4</property>
                         </child>
                       </object>
                       <packing>
+                        <property name="expand">False</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
index 95d6b2d..dd63ccf 100644 (file)
@@ -188,6 +188,7 @@ static options_map_t d_analyse_opts[] =
        {"Some", "some", 0, 0.0, "some"},
        {"None", "none", 1, 0.0, "none"},
        {"All",  "all",  2, 0.0, "all"},
+       {"Custom",  "custom",  3, 0.0, "all"},
 };
 combo_opts_t analyse_opts =
 {
@@ -197,9 +198,9 @@ combo_opts_t analyse_opts =
 
 static options_map_t d_trellis_opts[] =
 {
-       {"Disabled",          "off",    0, 0.0, ""},
-       {"Final Macro Block", "fmb",    1, 0.0, ""},
-       {"Always",            "always", 2, 0.0, ""},
+       {"Disabled",          "0",    0, 0.0, "0"},
+       {"Final Macro Block", "1",    1, 0.0, "1"},
+       {"Always",            "2", 2, 0.0, "2"},
 };
 combo_opts_t trellis_opts =
 {
@@ -1438,113 +1439,16 @@ static const char * turbo_opts =
 gchar*
 ghb_build_x264opts_string(GHashTable *settings)
 {
-       GString *x264opts = g_string_new("");
-       gint refs = ghb_settings_get_int(settings, "x264_refs");
-       if (refs != 1)
-       {
-               g_string_append_printf(x264opts, "ref=%d:", refs);
-       }
-       if (refs > 1)
-       {
-               if (ghb_settings_get_bool(settings, "x264_mixed_refs"))
-               {
-                       g_string_append(x264opts, "mixed-refs=1:");
-               }
-       }
-       gint subme = ghb_settings_get_int(settings, "x264_subme");
-       if (subme != 5) // 5 is default
-       {
-               g_string_append_printf(x264opts, "subme=%d:", subme);
-       }
-       gint bframes = ghb_settings_get_int(settings, "x264_bframes");
-       if (bframes > 0)
-       {
-               g_string_append_printf(x264opts, "bframes=%d:", bframes);
-               if (ghb_settings_get_bool(settings, "x264_weighted_bframes"))
-               {
-                       g_string_append(x264opts, "weightb=1:");
-               }
-               if (subme >= 6)
-               {
-                       if (ghb_settings_get_bool(settings, "x264_brdo"))
-                       {
-                               g_string_append(x264opts, "brdo=1:");
-                       }
-               }
-               if (ghb_settings_get_bool(settings, "x264_bime"))
-               {
-                       g_string_append(x264opts, "bime=1:");
-               }
-       }
-       if (bframes > 1)
-       {
-               if (ghb_settings_get_bool(settings, "x264_bpyramid"))
-               {
-                       g_string_append(x264opts, "b-pyramid=1:");
-               }
-       }
-       if (ghb_settings_get_bool(settings, "x264_no_fast_pskip"))
-       {
-               g_string_append(x264opts, "no-fast-pskip=1:");
-       }
-       if (ghb_settings_get_bool(settings, "x264_no_dct_decimate"))
-       {
-               g_string_append(x264opts, "no-dct-decimate=1:");
-       }
-       if (!ghb_settings_get_bool(settings, "x264_cabac"))
+       gchar *result;
+       const gchar *opts = ghb_settings_get_string(settings, "x264_options");
+       if (opts != NULL)
        {
-               g_string_append(x264opts, "cabac=0:");
+               result = g_strdup(opts);
        }
        else
        {
-               gint trellis = ghb_settings_get_int(settings, "x264_trellis");
-               if (trellis != 0); // != None
-               {
-                       g_string_append_printf(x264opts, "trellis=%d:", trellis);
-               }
-       }
-       gint dba, dbb;
-       dba = ghb_settings_get_int(settings, "x264_deblock_alpha");
-       dbb = ghb_settings_get_int(settings, "x264_deblock_beta");
-       if (dba != 0 || dbb != 0)
-       {
-               g_string_append_printf(x264opts, "deblock=%d,%d:", dba, dbb);
-       }
-       const gchar *me = ghb_settings_get_string(settings, "x264_me");
-       g_string_append_printf(x264opts, "me=%s:", me);
-       gint analyse = ghb_settings_get_int(settings, "x264_analyse");
-       if (analyse != 0) // != Some
-       {
-               g_string_append_printf(x264opts, "analyse=%s:", 
-                                                          ghb_settings_get_string(settings, "x264_analyse"));
+               result = g_strdup("");
        }
-       if (ghb_settings_get_bool(settings, "x264_8x8dct"))
-       {
-               g_string_append(x264opts, "8x8dct:");
-       }
-       if (analyse != 1) // != none
-       {
-               gint direct = ghb_settings_get_int(settings, "x264_direct");
-               if (direct != 1) // !spatial
-               {
-                       g_string_append_printf(x264opts, "direct=%s:", 
-                                                                  ghb_settings_get_string(settings, "x264_direct"));
-               }
-       }
-       g_string_append_printf(x264opts, "merange=%d:", 
-                                                  ghb_settings_get_int(settings, "x264_merange"));
-
-       const gchar *opts = ghb_settings_get_string(settings, "x264_options");
-       if (opts != NULL && opts[0] != 0)
-       {
-               g_string_append_printf(x264opts, "%s:", opts);
-       }
-       // strip the trailing ":"
-       gchar *result;
-       gint len;
-       result = g_string_free(x264opts, FALSE);
-       len = strlen(result);
-       if (len > 0) result[len - 1] = 0;
        return result;
 }
 
index 4206e64..0a8d33f 100644 (file)
@@ -42,26 +42,7 @@ vquality_type_target=disable
 video_bitrate=1800
 video_target_size=700
 video_quality=64
-x264_direct=spatial
-x264_weighted_bframes=disable
-x264_bime=disable
-x264_merange=16
 x264_options=
-x264_cabac=enable
-x264_deblock_beta=0
-x264_analyse=some
-x264_8x8dct=disable
-x264_bframes=0
-x264_no_dct_decimate=disable
-x264_subme=5
-x264_brdo=disable
-x264_bpyramid=disable
-x264_no_fast_pskip=disable
-x264_refs=1
-x264_me=umh
-x264_deblock_alpha=0
-x264_mixed_refs=disable
-x264_trellis=off
 directqp=disable
 
 [Initialization]
@@ -74,6 +55,25 @@ crop_top=0
 crop_bottom=0
 crop_left=0
 crop_right=0
+x264_refs=1
+x264_mixed_refs=disable
+x264_bframes=0
+x264_direct=spatial
+x264_weighted_bframes=disable
+x264_brdo=disable
+x264_bime=disable
+x264_bpyramid=disable
+x264_me=hex
+x264_merange=16
+x264_subme=5
+x264_analyse=some
+x264_8x8dct=disable
+x264_deblock_alpha=0
+x264_deblock_beta=0
+x264_trellis=0
+x264_no_fast_pskip=disable
+x264_no_dct_decimate=disable
+x264_cabac=enable
 
 [Preferences]
 version=0.1
index ea62833..28c5393 100644 (file)
 "video_bitrate=1800\n"
 "video_target_size=700\n"
 "video_quality=64\n"
-"x264_direct=spatial\n"
-"x264_weighted_bframes=disable\n"
-"x264_bime=disable\n"
-"x264_merange=16\n"
 "x264_options=\n"
-"x264_cabac=enable\n"
-"x264_deblock_beta=0\n"
-"x264_analyse=some\n"
-"x264_8x8dct=disable\n"
-"x264_bframes=0\n"
-"x264_no_dct_decimate=disable\n"
-"x264_subme=5\n"
-"x264_brdo=disable\n"
-"x264_bpyramid=disable\n"
-"x264_no_fast_pskip=disable\n"
-"x264_refs=1\n"
-"x264_me=umh\n"
-"x264_deblock_alpha=0\n"
-"x264_mixed_refs=disable\n"
-"x264_trellis=off\n"
 "directqp=disable\n"
 "\n"
 "[Initialization]\n"
 "crop_bottom=0\n"
 "crop_left=0\n"
 "crop_right=0\n"
+"x264_refs=1\n"
+"x264_mixed_refs=disable\n"
+"x264_bframes=0\n"
+"x264_direct=spatial\n"
+"x264_weighted_bframes=disable\n"
+"x264_brdo=disable\n"
+"x264_bime=disable\n"
+"x264_bpyramid=disable\n"
+"x264_me=hex\n"
+"x264_merange=16\n"
+"x264_subme=5\n"
+"x264_analyse=some\n"
+"x264_8x8dct=disable\n"
+"x264_deblock_alpha=0\n"
+"x264_deblock_beta=0\n"
+"x264_trellis=0\n"
+"x264_no_fast_pskip=disable\n"
+"x264_no_dct_decimate=disable\n"
+"x264_cabac=enable\n"
 "\n"
 "[Preferences]\n"
 "version=0.1\n"
index 0d5ffad..53b71d9 100644 (file)
@@ -463,6 +463,8 @@ watch_volumes(signal_user_data_t *ud)
 extern int mm_flags;
 int mm_support();
 
+void x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud);
+
 int
 main (int argc, char *argv[])
 {
@@ -515,6 +517,15 @@ main (int argc, char *argv[])
                ud->builder = create_builder_or_die (BUILDER_NAME, builder_file);
                g_free(builder_file);
        }
+
+       // Need to connect x264_options textview buffer to the changed signal
+       // since it can't be done automatically
+       GtkTextView *textview;
+       GtkTextBuffer *buffer;
+       textview = GTK_TEXT_VIEW(GHB_WIDGET (ud->builder, "x264_options"));
+       buffer = gtk_text_view_get_buffer (textview);
+       g_signal_connect(buffer, "changed", (GCallback)x264_entry_changed_cb, ud);
+
        ghb_file_menu_add_dvd(ud);
        ghb_backend_init(ud->builder, 1, 0);
 
@@ -555,6 +566,8 @@ main (int argc, char *argv[])
                if (preset == NULL)
                        preset = ghb_presets_get_name(0);
        }
+       // Parsing x264 options "" initializes x264 widgets to proper defaults
+       ghb_x264_parse_options(ud, "");
        ghb_select_preset(ud->builder, preset);
        ghb_prefs_to_ui(ud);
        // Grey out widgets that are dependent on a disabled feature
index 31678de..1e78fcb 100644 (file)
@@ -311,12 +311,13 @@ ghb_widget_value(GtkWidget *widget)
                return NULL;
        }
        value = g_malloc(sizeof(setting_value_t));
+
+       type = GTK_WIDGET_TYPE(widget);
        if (GTK_IS_ACTION(widget))
                name = gtk_action_get_name(GTK_ACTION(widget));
        else
                name = gtk_widget_get_name(widget);
        g_debug("ghb_widget_value widget (%s)\n", name);
-       type = GTK_OBJECT_TYPE(widget);
        if (type == GTK_TYPE_ENTRY)
        {
                const gchar *str = gtk_entry_get_text((GtkEntry*)widget);
@@ -336,7 +337,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tenable");
                        value->option = g_strdup("enable");
                        value->shortOpt = g_strdup("enable");
-                       value->svalue = g_strdup("enable");
+                       value->svalue = g_strdup("1");
                        value->ivalue = 1;
                        value->dvalue = 1;
                }
@@ -345,7 +346,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tdisable");
                        value->option = g_strdup("disable");
                        value->shortOpt = g_strdup("disable");
-                       value->svalue = g_strdup("disable");
+                       value->svalue = g_strdup("0");
                        value->ivalue = 0;
                        value->dvalue = 0;
                }
@@ -359,7 +360,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tenable");
                        value->option = g_strdup("enable");
                        value->shortOpt = g_strdup("enable");
-                       value->svalue = g_strdup("enable");
+                       value->svalue = g_strdup("1");
                        value->ivalue = 1;
                        value->dvalue = 1;
                }
@@ -368,7 +369,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tdisable");
                        value->option = g_strdup("disable");
                        value->shortOpt = g_strdup("disable");
-                       value->svalue = g_strdup("disable");
+                       value->svalue = g_strdup("0");
                        value->ivalue = 0;
                        value->dvalue = 0;
                }
@@ -382,7 +383,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tenable");
                        value->option = g_strdup("enable");
                        value->shortOpt = g_strdup("enable");
-                       value->svalue = g_strdup("enable");
+                       value->svalue = g_strdup("1");
                        value->ivalue = 1;
                        value->dvalue = 1;
                }
@@ -391,7 +392,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tdisable");
                        value->option = g_strdup("disable");
                        value->shortOpt = g_strdup("disable");
-                       value->svalue = g_strdup("disable");
+                       value->svalue = g_strdup("0");
                        value->ivalue = 0;
                        value->dvalue = 0;
                }
@@ -405,7 +406,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tenable");
                        value->option = g_strdup("enable");
                        value->shortOpt = g_strdup("enable");
-                       value->svalue = g_strdup("enable");
+                       value->svalue = g_strdup("1");
                        value->ivalue = 1;
                        value->dvalue = 1;
                }
@@ -414,7 +415,7 @@ ghb_widget_value(GtkWidget *widget)
                        g_debug("\tdisable");
                        value->option = g_strdup("disable");
                        value->shortOpt = g_strdup("disable");
-                       value->svalue = g_strdup("disable");
+                       value->svalue = g_strdup("0");
                        value->ivalue = 0;
                        value->dvalue = 0;
                }
@@ -477,7 +478,6 @@ ghb_widget_value(GtkWidget *widget)
                value->svalue = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
                value->option = g_strdup(value->svalue);
                value->shortOpt = g_strdup(value->svalue);
-               g_debug("text view (%s)\n", value->svalue);
                value->ivalue = 0;
                value->dvalue = 0;
                value->index = 0;
@@ -627,7 +627,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue)
        GType type;
        gchar *value;
 
-       g_debug("update_widget\n");
+       g_debug("update_widget");
        // make a dup of setting value because the setting hash gets 
        // modified and thus the value pointer can become invalid.
        if (parm_svalue == NULL)
@@ -638,31 +638,31 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue)
        {
                value = g_strdup(parm_svalue);
        }
-       g_debug("update widget value (%s)\n", value);
+       g_debug("update widget value (%s)", value);
        type = GTK_OBJECT_TYPE(widget);
        if (type == GTK_TYPE_ENTRY)
        {
-               g_debug("entry\n");
+               g_debug("entry");
                gtk_entry_set_text((GtkEntry*)widget, value);
        }
        else if (type == GTK_TYPE_RADIO_BUTTON)
        {
-               g_debug("radio button\n");
+               g_debug("radio button");
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), string_is_true(value));
        }
        else if (type == GTK_TYPE_CHECK_BUTTON)
        {
-               g_debug("check button\n");
+               g_debug("check button");
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), string_is_true(value));
        }
        else if (type == GTK_TYPE_TOGGLE_ACTION)
        {
-               g_debug("toggle action\n");
+               g_debug("toggle action");
                gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(widget), string_is_true(value));
        }
        else if (type == GTK_TYPE_CHECK_MENU_ITEM)
        {
-               g_debug("check menu item\n");
+               g_debug("check menu item");
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), string_is_true(value));
        }
        else if (type == GTK_TYPE_COMBO_BOX)
@@ -673,6 +673,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue)
                gint ivalue;
                gboolean foundit = FALSE;
 
+               g_debug("combo");
                store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
                if (gtk_tree_model_get_iter_first (store, &iter))
                {
@@ -705,7 +706,7 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue)
        {
                gdouble val;
                
-               g_debug("spin\n");
+               g_debug("spin (%s)", value);
                val = g_strtod(value, NULL);
                gtk_spin_button_set_value((GtkSpinButton*)widget, val);
        }
@@ -713,18 +714,19 @@ update_widget(GtkWidget *widget, const gchar *parm_svalue, gint parm_ivalue)
        {
                gdouble val;
                
-               g_debug("hscale\n");
+               g_debug("hscale");
                val = g_strtod(value, NULL);
                gtk_range_set_value((GtkRange*)widget, val);
        }
        else if (type == GTK_TYPE_TEXT_VIEW)
        {
+               g_debug("textview (%s)", value);
                GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
                gtk_text_buffer_set_text (buffer, value, -1);
        }
        else
        {
-               g_debug("Attempt to set unknown widget type\n");
+               g_debug("Attempt to set unknown widget type");
        }
        g_free(value);
 }
@@ -753,7 +755,7 @@ ghb_ui_update_int(signal_user_data_t *ud, const gchar *name, gint ivalue)
 {
        GObject *object;
 
-       g_debug("ghb_ui_update ()\n");
+       g_debug("ghb_ui_update_int ()\n");
        object = GHB_OBJECT(ud->builder, name);
        if (object == NULL)
        {
@@ -1542,3 +1544,471 @@ ghb_presets_remove(GHashTable *settings, const gchar *name)
        return FALSE;
 }
 
+enum
+{
+       X264_OPT_DEBLOCK,
+       X264_OPT_INT,
+       X264_OPT_COMBO,
+       X264_OPT_BOOL,
+};
+
+struct x264_opt_map_s
+{
+       gchar **opt_syns;
+       gchar *name;
+       gchar *def_val;
+       gint type;
+       gboolean found;
+};
+
+static gchar *x264_ref_syns[] = {"ref", "frameref", NULL};
+static gchar *x264_mixed_syns[] = {"mixed-refs", NULL};
+static gchar *x264_bframes_syns[] = {"bframes", NULL};
+static gchar *x264_direct_syns[] = {"direct", "direct-pred", NULL};
+static gchar *x264_weightb_syns[] = {"weightb", "weight-b", NULL};
+static gchar *x264_brdo_syns[] = {"brdo", "b-rdo", NULL};
+static gchar *x264_bime_syns[] = {"bime", NULL};
+static gchar *x264_bpyramid_syns[] = {"b-pyramid", NULL};
+static gchar *x264_me_syns[] = {"me", NULL};
+static gchar *x264_merange_syns[] = {"merange", "me-range", NULL};
+static gchar *x264_subme_syns[] = {"subme", "subq", NULL};
+static gchar *x264_analyse_syns[] = {"analyse", "partitions", NULL};
+static gchar *x264_8x8dct_syns[] = {"8x8dct", NULL};
+static gchar *x264_deblock_syns[] = {"deblock", "filter", NULL};
+static gchar *x264_trellis_syns[] = {"trellis", NULL};
+static gchar *x264_pskip_syns[] = {"no-fast-pskip", NULL};
+static gchar *x264_decimate_syns[] = {"no-dct-decimate", NULL};
+static gchar *x264_cabac_syns[] = {"cabac", NULL};
+
+static gint
+find_syn_match(const gchar *opt, gchar **syns)
+{
+       gint ii;
+       for (ii = 0; syns[ii] != NULL; ii++)
+       {
+               if (strcmp(opt, syns[ii]) == 0)
+                       return ii;
+       }
+       return -1;
+}
+
+struct x264_opt_map_s x264_opt_map[] =
+{
+       {x264_ref_syns, "x264_refs", "1", X264_OPT_INT},
+       {x264_mixed_syns, "x264_mixed_refs", "0", X264_OPT_BOOL},
+       {x264_bframes_syns, "x264_bframes", "0", X264_OPT_INT},
+       {x264_direct_syns, "x264_direct", "spatial", X264_OPT_COMBO},
+       {x264_weightb_syns, "x264_weighted_bframes", "0", X264_OPT_BOOL},
+       {x264_brdo_syns, "x264_brdo", "0", X264_OPT_BOOL},
+       {x264_bime_syns, "x264_bime", "0", X264_OPT_BOOL},
+       {x264_bpyramid_syns, "x264_bpyramid", "0", X264_OPT_BOOL},
+       {x264_me_syns, "x264_me", "hex", X264_OPT_COMBO},
+       {x264_merange_syns, "x264_merange", "16", X264_OPT_INT},
+       {x264_subme_syns, "x264_subme", "5", X264_OPT_COMBO},
+       {x264_analyse_syns, "x264_analyse", "some", X264_OPT_COMBO},
+       {x264_8x8dct_syns, "x264_8x8dct", "0", X264_OPT_BOOL},
+       {x264_deblock_syns, "x264_deblock_alpha", "0,0", X264_OPT_DEBLOCK},
+       {x264_deblock_syns, "x264_deblock_beta", "0,0", X264_OPT_DEBLOCK},
+       {x264_trellis_syns, "x264_trellis", "0", X264_OPT_COMBO},
+       {x264_pskip_syns, "x264_no_fast_pskip", "0", X264_OPT_BOOL},
+       {x264_decimate_syns, "x264_no_dct_decimate", "0", X264_OPT_BOOL},
+       {x264_cabac_syns, "x264_cabac", "1", X264_OPT_BOOL},
+};
+#define X264_OPT_MAP_SIZE (sizeof(x264_opt_map)/sizeof(struct x264_opt_map_s))
+
+static const gchar*
+x264_opt_get_default(const gchar *opt)
+{
+       gint jj;
+       for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++)
+       {
+               if (find_syn_match(opt, x264_opt_map[jj].opt_syns) >= 0)
+               {
+                       return x264_opt_map[jj].def_val;
+               }
+       }
+       return "";
+}
+
+static void
+x264_update_int(signal_user_data_t *ud, const gchar *name, const gchar *val)
+{
+       gdouble dvalue;
+       gchar *end;
+
+       if (val == NULL) return;
+       dvalue = g_strtod (val, &end);
+       ghb_ui_update_int(ud, name, dvalue);
+}
+
+static void
+x264_update_bool(signal_user_data_t *ud, const gchar *name, const gchar *val)
+{
+       if (val == NULL)
+               ghb_ui_update(ud, name, "1");
+       else
+               ghb_ui_update(ud, name, val);
+}
+
+static void
+x264_update_combo(signal_user_data_t *ud, const gchar *name, const gchar *val)
+{
+       GtkTreeModel *store;
+       GtkTreeIter iter;
+       gchar *shortOpt;
+       gint ivalue;
+       gboolean foundit = FALSE;
+       GtkWidget *widget;
+
+       if (val == NULL) return;
+       widget = GHB_WIDGET(ud->builder, name);
+       if (widget == NULL)
+       {
+               g_debug("Failed to find widget for key: %s\n", name);
+               return;
+       }
+       store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
+       if (gtk_tree_model_get_iter_first (store, &iter))
+       {
+               do
+               {
+                       gtk_tree_model_get(store, &iter, 2, &shortOpt, 3, &ivalue, -1);
+                       if (strcmp(shortOpt, val) == 0)
+                       {
+                               gtk_combo_box_set_active_iter (GTK_COMBO_BOX(widget), &iter);
+                               g_free(shortOpt);
+                               foundit = TRUE;
+                               break;
+                       }
+                       g_free(shortOpt);
+               } while (gtk_tree_model_iter_next (store, &iter));
+       }
+       if (!foundit)
+       {
+               if (gtk_tree_model_get_iter_first (store, &iter))
+               {
+                       do
+                       {
+                               gtk_tree_model_get(store, &iter, 2, &shortOpt, 3, &ivalue, -1);
+                               if (strcmp(shortOpt, "custom") == 0)
+                               {
+                                       gtk_list_store_set(GTK_LIST_STORE(store), &iter, 4, val, -1);
+                                       gtk_combo_box_set_active_iter (GTK_COMBO_BOX(widget), &iter);
+                                       g_free(shortOpt);
+                                       foundit = TRUE;
+                                       break;
+                               }
+                               g_free(shortOpt);
+                       } while (gtk_tree_model_iter_next (store, &iter));
+               }
+       }
+       // Its possible the value hasn't changed. Since settings are only
+       // updated when the value changes, I'm initializing settings here as well.
+       ghb_widget_to_setting(ud->settings, widget);
+}
+
+static void
+x264_update_deblock(signal_user_data_t *ud, const gchar *xval)
+{
+       gdouble avalue, bvalue;
+       gchar *end;
+       gchar *val;
+       gchar *bval = NULL;
+
+       if (xval == NULL) return;
+       val = g_strdup(xval);
+       bvalue = avalue = 0;
+       if (val != NULL) 
+       {
+               gchar *pos = strchr(val, ',');
+               if (pos != NULL)
+               {
+                       bval = pos + 1;
+                       *pos = 0;
+               }
+               avalue = g_strtod (val, &end);
+               if (bval != NULL)
+               {
+                       bvalue = g_strtod (bval, &end);
+               }
+       }
+       g_free(val);
+       ghb_ui_update_int(ud, "x264_deblock_alpha", avalue);
+       ghb_ui_update_int(ud, "x264_deblock_beta", bvalue);
+}
+
+void
+ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options)
+{
+       gchar **split = g_strsplit(options, ":", -1);
+       if (split == NULL) return;
+
+       gint ii;
+       gint jj;
+
+       for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++)
+               x264_opt_map[jj].found = FALSE;
+
+       for (ii = 0; split[ii] != NULL; ii++)
+       {
+               gchar *val = NULL;
+               gchar *pos = strchr(split[ii], '=');
+               if (pos != NULL)
+               {
+                       val = pos + 1;
+                       *pos = 0;
+               }
+               for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++)
+               {
+                       if (find_syn_match(split[ii], x264_opt_map[jj].opt_syns) >= 0)
+                       {
+                               x264_opt_map[jj].found = TRUE;
+                               switch(x264_opt_map[jj].type)
+                               {
+                               case X264_OPT_INT:
+                                       x264_update_int(ud, x264_opt_map[jj].name, val);
+                                       break;
+                               case X264_OPT_BOOL:
+                                       x264_update_bool(ud, x264_opt_map[jj].name, val);
+                                       break;
+                               case X264_OPT_COMBO:
+                                       x264_update_combo(ud, x264_opt_map[jj].name, val);
+                                       break;
+                               case X264_OPT_DEBLOCK:
+                                       // dirty little hack.  mark deblock_beta found as well
+                                       x264_opt_map[jj+1].found = TRUE;
+                                       x264_update_deblock(ud, val);
+                                       break;
+                               }
+                               break;
+                       }
+               }
+       }
+       // For any options not found in the option string, set ui to
+       // default values
+       for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++)
+       {
+               if (!x264_opt_map[jj].found)
+               {
+                       gchar *val = strdup(x264_opt_map[jj].def_val);
+                       switch(x264_opt_map[jj].type)
+                       {
+                       case X264_OPT_INT:
+                               x264_update_int(ud, x264_opt_map[jj].name, val);
+                               break;
+                       case X264_OPT_BOOL:
+                               x264_update_bool(ud, x264_opt_map[jj].name, val);
+                               break;
+                       case X264_OPT_COMBO:
+                               x264_update_combo(ud, x264_opt_map[jj].name, val);
+                               break;
+                       case X264_OPT_DEBLOCK:
+                               x264_update_deblock(ud, val);
+                               break;
+                       }
+                       x264_opt_map[jj].found = TRUE;
+                       g_free(val);
+               }
+       }
+       g_strfreev(split);
+}
+
+gchar*
+get_deblock_val(signal_user_data_t *ud)
+{
+       const gchar *alpha, *beta;
+       gchar *result;
+       alpha = ghb_settings_get_string(ud->settings, "x264_deblock_alpha");
+       beta = ghb_settings_get_string(ud->settings, "x264_deblock_beta");
+       result = g_strdup_printf("%s,%s", alpha, beta);
+       return result;
+}
+
+void
+ghb_x264_opt_update(signal_user_data_t *ud, GtkWidget *widget)
+{
+       gint jj;
+       const gchar *name = gtk_widget_get_name(widget);
+       gchar **opt_syns = NULL;
+       const gchar *def_val = NULL;
+       gint type;
+
+       for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++)
+       {
+               if (strcmp(name, x264_opt_map[jj].name) == 0)
+               {
+                       // found the options that needs updating
+                       opt_syns = x264_opt_map[jj].opt_syns;
+                       def_val = x264_opt_map[jj].def_val;
+                       type = x264_opt_map[jj].type;
+                       break;
+               }
+       }
+       if (opt_syns != NULL)
+       {
+               GString *x264opts = g_string_new("");
+               const gchar *options;
+               options = ghb_settings_get_string(ud->settings, "x264_options");
+               gchar **split = g_strsplit(options, ":", -1);
+               gint ii;
+               gboolean foundit = FALSE;
+
+               if (split == NULL) return;
+               for (ii = 0; split[ii] != NULL; ii++)
+               {
+                       gint syn;
+                       gchar *val = NULL;
+                       gchar *pos = strchr(split[ii], '=');
+                       if (pos != NULL)
+                       {
+                               val = pos + 1;
+                               *pos = 0;
+                       }
+                       syn = find_syn_match(split[ii], opt_syns);
+                       if (syn >= 0)
+                       { // Updating this option
+                               gchar *val;
+                               foundit = TRUE;
+                               if (type == X264_OPT_DEBLOCK)
+                                       val = get_deblock_val(ud);
+                               else
+                                       val = ghb_widget_string(widget);
+                               if (strcmp(def_val, val) != 0)
+                               {
+                                       g_string_append_printf(x264opts, "%s=%s:", opt_syns[syn], val);
+                               }
+                               g_free(val);
+                       }
+                       else if (val != NULL)
+                               g_string_append_printf(x264opts, "%s=%s:", split[ii], val);
+                       else
+                               g_string_append_printf(x264opts, "%s:", split[ii]);
+
+               }
+               if (!foundit)
+               {
+                       gchar *val;
+                       if (type == X264_OPT_DEBLOCK)
+                               val = get_deblock_val(ud);
+                       else
+                               val = ghb_widget_string(widget);
+                       if (strcmp(def_val, val) != 0)
+                       {
+                               g_string_append_printf(x264opts, "%s=%s:", opt_syns[0], val);
+                       }
+                       g_free(val);
+               }
+               // Update the options value
+               // strip the trailing ":"
+               gchar *result;
+               gint len;
+               result = g_string_free(x264opts, FALSE);
+               len = strlen(result);
+               if (len > 0) result[len - 1] = 0;
+               ghb_ui_update(ud, "x264_options", result);
+       }
+}
+
+static void
+x264_remove_opt(gchar **opts, gchar **opt_syns)
+{
+       gint ii;
+       for (ii = 0; opts[ii] != NULL; ii++)
+       {
+               gchar *opt;
+               opt = g_strdup(opts[ii]);
+               gchar *pos = strchr(opt, '=');
+               if (pos != NULL)
+               {
+                       *pos = 0;
+               }
+               if (find_syn_match(opt, opt_syns) >= 0)
+               {
+                       // Mark as deleted
+                       opts[ii][0] = 0;
+               }
+               g_free(opt);
+       }
+}
+
+// Construct the x264 options string
+// The result is allocated, so someone must free it at some point.
+gchar*
+ghb_sanitize_x264opts(signal_user_data_t *ud, const gchar *options)
+{
+       GString *x264opts = g_string_new("");
+       gchar **split = g_strsplit(options, ":", -1);
+
+       // Remove entries that match the defaults
+       gint ii;
+       for (ii = 0; split[ii] != NULL; ii++)
+       {
+               gchar *val = NULL;
+               gchar *opt = g_strdup(split[ii]);
+               gchar *pos = strchr(opt, '=');
+               if (pos != NULL)
+               {
+                       val = pos + 1;
+                       *pos = 0;
+               }
+               else
+               {
+                       val = "1";
+               }
+               const gchar *def_val = x264_opt_get_default(opt);
+               if (strcmp(val, def_val) == 0)
+               {
+                       // Matches the default, so remove it
+                       split[ii][0] = 0;
+               }
+               g_free(opt);
+       }
+       gint refs = ghb_settings_get_int(ud->settings, "x264_refs");
+       if (refs <= 1)
+       {
+               x264_remove_opt(split, x264_mixed_syns);
+       }
+       gint subme = ghb_settings_get_int(ud->settings, "x264_subme");
+       if (subme < 6)
+       {
+               x264_remove_opt(split, x264_brdo_syns);
+       }
+       gint bframes = ghb_settings_get_int(ud->settings, "x264_bframes");
+       if (bframes == 0)
+       {
+               x264_remove_opt(split, x264_weightb_syns);
+               x264_remove_opt(split, x264_brdo_syns);
+               x264_remove_opt(split, x264_bime_syns);
+       }
+       if (bframes <= 1)
+       {
+               x264_remove_opt(split, x264_bpyramid_syns);
+       }
+       const gchar *me = ghb_settings_get_string(ud->settings, "x264_me");
+       if (!(strcmp(me, "umh") == 0 || strcmp(me, "esa") == 0))
+       {
+               x264_remove_opt(split, x264_merange_syns);
+       }
+       if (!ghb_settings_get_bool(ud->settings, "x264_cabac"))
+       {
+               x264_remove_opt(split, x264_trellis_syns);
+       }
+       gint analyse = ghb_settings_get_int(ud->settings, "x264_analyse");
+       if (analyse == 1)
+       {
+               x264_remove_opt(split, x264_direct_syns);
+       }
+       for (ii = 0; split[ii] != NULL; ii++)
+       {
+               if (split[ii][0] != 0)
+                       g_string_append_printf(x264opts, "%s:", split[ii]);
+       }
+       // strip the trailing ":"
+       gchar *result;
+       gint len;
+       result = g_string_free(x264opts, FALSE);
+       len = strlen(result);
+       if (len > 0) result[len - 1] = 0;
+       return result;
+}
+
index 1610078..44f7f90 100644 (file)
@@ -125,5 +125,8 @@ void ghb_prefs_to_ui(signal_user_data_t *ud);
 void ghb_prefs_save(GHashTable *settings);
 void ghb_pref_save(GHashTable *settings, const gchar *key);
 void ghb_set_preset_default(GHashTable *settings);
+void ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options);
+void ghb_x264_opt_update(signal_user_data_t *ud, GtkWidget *widget);
+gchar* ghb_sanitize_x264opts(signal_user_data_t *ud, const gchar *options);
 
 #endif // _SETTINGS_H_
index 3d15624..68e03bd 100755 (executable)
@@ -3,18 +3,7 @@ preset_description=HandBrake's settings for the Microsoft Xbox 360.
 container=mp4
 chapter_markers=disable
 video_codec=x264
-x264_refs=2
-x264_mixed_refs=enable
-x264_bframes=3
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=5
-x264_analyse=all
-x264_no_fast_pskip=enable
-x264_options=level=40:filter=-2,-1
+x264_options=level=40:ref=2:mixed-refs:bframes=3:bime:weightb:direct=auto:b-pyramid:me=umh:subme=5:analyse=all:no-fast-pskip:filter=-2,-1
 vquality_type_bitrate=enable
 video_bitrate=2000
 video_target_size=700
@@ -41,20 +30,7 @@ preset_description=HandBrake's settings for cartoons, anime, and CGI.
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=5
-x264_mixed_refs=enable
-x264_bframes=6
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=5
-x264_analyse=all
-x264_8x8dct=enable
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_options=nr=150:filter=2,2
+x264_options=ref=5:mixed-refs:bframes=6:bime:weightb:direct=auto:b-pyramid:me=umh:subme=5:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip:filter=2,2
 vquality_type_bitrate=enable
 video_bitrate=1000
 video_target_size=700
@@ -83,13 +59,7 @@ container=m4v
 large_mp4=enable
 chapter_markers=enable
 video_codec=x264
-x264_refs=1
-x264_bframes=3
-x264_me=umh
-x264_subme=5
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_cabac=disable
+x264_options=bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:cabac=0
 vquality_type_bitrate=enable
 video_bitrate=2500
 video_target_size=700
@@ -117,23 +87,7 @@ preset_description=HandBrake's settings maxed out for slowest encoding and highe
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=16
-x264_mixed_refs=enable
-x264_bframes=16
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=esa
-x264_merange=64
-x264_subme=7
-x264_analyse=all
-x264_8x8dct=enable
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_no_dct_decimate=enable
-x264_options=filter=-2,-1
+x264_options=ref=16:mixed-refs:bframes=16:bime:weightb:b-rdo:direct=auto:b-pyramid:me=esa:subme=7:me-range=64:analyse=all:8x8dct:trellis=1:no-fast-pskip:no-dct-decimate:filter=-2,-1
 vquality_type_bitrate=enable
 video_bitrate=1800
 video_target_size=700
@@ -188,20 +142,7 @@ preset_description=HandBrake's preset for people without a lot of money to waste
 container=mp4
 chapter_markers=enable
 video_codec=x264
-x264_refs=3
-x264_mixed_refs=enable
-x264_bframes=16
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_bpyramid=enable
-x264_direct=auto
-x264_me=umh
-x264_subme=6
-x264_trellis=fmb
-x264_analyse=all
-x264_8x8dct=enable
-x264_no_fast_pskip=enable
+x264_options=ref=3:mixed-refs:bframes=16:bime:weightb:b-rdo:b-pyramid:direct=auto:me=umh:subme=6:trellis=1:analyse=all:8x8dct:no-fast-pskip
 vquality_type_target=enable
 video_bitrate=1600
 video_target_size=695
@@ -256,18 +197,7 @@ preset_description=HandBrake's preset for consistently excellent quality in one
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=3
-x264_mixed_refs=enable
-x264_bframes=3
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=6
-x264_analyse=all
-x264_8x8dct=enable
-x264_options=filter=-2,-1
+x264_options=ref=3:mixed-refs:bframes=3:b-pyramid:b-rdo:bime:weightb:filter=-2,-1:subme=6:trellis=1:analyse=all:8x8dct:me=umh
 vquality_type_constant=enable
 video_bitrate=2000
 video_target_size=700
@@ -294,19 +224,7 @@ preset_description=HandBrake's preset for true high profile x264 quality. A good
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=5
-x264_mixed_refs=enable
-x264_bframes=3
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=7
-x264_analyse=all
-x264_8x8dct=enable
-x264_trellis=fmb
-x264_no_fast_pskip=enable
+x264_options=ref=5:mixed-refs:bframes=3:bime:weightb:b-rdo:b-pyramid:me=umh:subme=7:trellis=1:analyse=all:8x8dct:no-fast-pskip
 vquality_type_bitrate=enable
 video_bitrate=1600
 video_target_size=700
@@ -334,20 +252,7 @@ preset_description=HandBrake's preset for feature films.
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=3
-x264_mixed_refs=enable
-x264_bframes=6
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=7
-x264_analyse=all
-x264_8x8dct=enable
-x264_trellis=fmb
-x264_no_fast_pskip=enable
+x264_options=ref=3:mixed-refs:bframes=6:bime:weightb:b-rdo:direct=auto:b-pyramid:me=umh:subme=7:analyse=all:8x8dct:trellis=1:no-fast-pskip
 vquality_type_bitrate=enable
 video_bitrate=1800
 video_target_size=700
@@ -376,14 +281,7 @@ container=mp4
 ipod_file=enable
 chapter_markers=enable
 video_codec=x264
-x264_refs=1
-x264_me=umh
-x264_subme=6
-x264_analyse=all
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_cabac=disable
-x264_options=level=30
+x264_options=level=30:cabac=0:ref=1:analyse=all:me=umh:subme=6:no-fast-pskip=1
 vquality_type_bitrate=enable
 video_bitrate=960
 video_target_size=700
@@ -412,14 +310,7 @@ container=mp4
 ipod_file=enable
 chapter_markers=enable
 video_codec=x264
-x264_refs=1
-x264_me=umh
-x264_subme=6
-x264_analyse=all
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_cabac=disable
-x264_options=level=30:vbv-maxrate=1500:vbv-bufsize=2000
+x264_options=level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1
 vquality_type_bitrate=enable
 video_bitrate=1500
 video_target_size=700
@@ -448,13 +339,7 @@ container=mp4
 ipod_file=enable
 chapter_markers=enable
 video_codec=x264
-x264_refs=1
-x264_me=umh
-x264_subme=6
-x264_analyse=all
-x264_no_fast_pskip=enable
-x264_cabac=disable
-x264_options=level=30:vbv-maxrate=768:vbv-bufsize=2000
+x264_options=level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1
 vquality_type_bitrate=enable
 video_bitrate=700
 video_target_size=700
@@ -482,10 +367,7 @@ preset_description=HandBrake's normal, default settings.
 container=mp4
 chapter_markers=enable
 video_codec=x264
-x264_refs=2
-x264_bframes=2
-x264_me=umh
-x264_subme=5
+x264_options=ref=2:bframes=2:subme=5:me=umh
 vquality_type_bitrate=enable
 video_bitrate=1500
 video_target_size=700
@@ -511,7 +393,6 @@ subtitles=disable
 [PSP]
 preset_description=HandBrake's settings for the Sony PlayStation Portable.
 container=mp4
-chapter_markers=enable
 video_codec=ffmpeg
 vquality_type_bitrate=enable
 video_bitrate=1024
@@ -541,9 +422,7 @@ preset_description=HandBrake's settings for the Sony PlayStation 3.
 container=mp4
 chapter_markers=disable
 video_codec=x264
-x264_me=umh
-x264_subme=5
-x264_options=level=41
+x264_options=level=41:subme=5:me=umh
 vquality_type_bitrate=enable
 video_bitrate=2500
 video_target_size=700
@@ -570,18 +449,7 @@ preset_description=HandBrake's high quality settings for use with QuickTime. It
 container=m4v
 chapter_markers=enable
 video_codec=x264
-x264_refs=3
-x264_mixed_refs=enable
-x264_bframes=3
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=5
-x264_analyse=all
-x264_trellis=fmb
-x264_no_fast_pskip=enable
+x264_options=ref=3:mixed-refs:bframes=3:bime:weightb:direct=auto:me=umh:subme=5:analyse=all:trellis=1:no-fast-pskip
 vquality_type_bitrate=enable
 video_bitrate=2000
 video_target_size=700
@@ -609,21 +477,7 @@ preset_description=HandBrake's settings for video from television.
 container=mkv
 chapter_markers=enable
 video_codec=x264
-x264_refs=3
-x264_mixed_refs=enable
-x264_bframes=6
-x264_bime=enable
-x264_weighted_bframes=enable
-x264_brdo=enable
-x264_direct=auto
-x264_bpyramid=enable
-x264_me=umh
-x264_subme=6
-x264_analyse=all
-x264_8x8dct=enable
-x264_trellis=fmb
-x264_no_fast_pskip=enable
-x264_options=nr=150
+x264_options=ref=3:mixed-refs:bframes=6:bime:weightb:direct=auto:b-pyramid:me=umh:subme=6:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip
 vquality_type_bitrate=enable
 video_bitrate=1300
 video_target_size=700