X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=gtk%2Fsrc%2Fx264handler.c;h=72883d85a7cb002daa23958649a149ffe373eb1b;hb=4b72a63eb61a01275493c4bfb51ba02152d1c5e1;hp=20ec56e5f0d133ddcbf3a7cd2512359c1c8ffaa0;hpb=d30e717f9c1508618527e93e2f26412cddfc2d3b;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/gtk/src/x264handler.c b/gtk/src/x264handler.c index 20ec56e5..72883d85 100644 --- a/gtk/src/x264handler.c +++ b/gtk/src/x264handler.c @@ -20,13 +20,14 @@ #include "hb-backend.h" #include "x264handler.h" +gint ghb_lookup_bframes(const gchar *options); static void x264_opt_update(signal_user_data_t *ud, GtkWidget *widget); static gchar* sanitize_x264opts(signal_user_data_t *ud, const gchar *options); // Flag needed to prevent x264 options processing from chasing its tail static gboolean ignore_options_update = FALSE; -void +G_MODULE_EXPORT void x264_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { ghb_widget_to_setting(ud->settings, widget); @@ -36,11 +37,43 @@ x264_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) x264_opt_update(ud, widget); ignore_options_update = FALSE; } - ghb_check_dependency(ud, widget); + ghb_check_dependency(ud, widget, NULL); ghb_clear_presets_selection(ud); } -void +G_MODULE_EXPORT void +x264_slider_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + + // Lock slider values to multiples of step_increment + GtkAdjustment * adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + gdouble step = gtk_adjustment_get_step_increment(adj); + gdouble val = gtk_range_get_value(GTK_RANGE(widget)); + gdouble new_val = ((int)((val + step / 2) / step)) * step; + gdouble diff = val - new_val; + if ( diff > 0.0001 || diff < -0.0001 ) + { + gtk_range_set_value(GTK_RANGE(widget), new_val); + } + else if (!ignore_options_update) + { + ignore_options_update = TRUE; + x264_opt_update(ud, widget); + ignore_options_update = FALSE; + } + ghb_check_dependency(ud, widget, NULL); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT gchar* +x264_format_slider_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud) +{ + return g_strdup_printf("%-6.6g", val); +} + + +G_MODULE_EXPORT void x264_me_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { gint me; @@ -52,7 +85,7 @@ x264_me_changed_cb(GtkWidget *widget, signal_user_data_t *ud) x264_opt_update(ud, widget); ignore_options_update = FALSE; } - ghb_check_dependency(ud, widget); + ghb_check_dependency(ud, widget, NULL); ghb_clear_presets_selection(ud); widget = GHB_WIDGET(ud->builder, "x264_merange"); me = ghb_settings_combo_int(ud->settings, "x264_me"); @@ -68,7 +101,7 @@ x264_me_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } } -void +G_MODULE_EXPORT void x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { g_debug("x264_entry_changed_cb ()"); @@ -96,7 +129,7 @@ x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } } -gboolean +G_MODULE_EXPORT gboolean x264_focus_out_cb(GtkWidget *widget, GdkEventFocus *event, signal_user_data_t *ud) { @@ -119,39 +152,95 @@ x264_focus_out_cb(GtkWidget *widget, GdkEventFocus *event, enum { + X264_OPT_NONE, + X264_OPT_BOOL_NONE, + X264_OPT_INT_NONE, X264_OPT_DEBLOCK, X264_OPT_PSY, X264_OPT_INT, + X264_OPT_DOUBLE, X264_OPT_COMBO, X264_OPT_BOOL, + X264_OPT_TRANS, }; +typedef struct +{ + gchar *x264_val; + char *ui_val; +} trans_entry_t; + +typedef struct +{ + gint count; + gint x264_type; + gint ui_type; + trans_entry_t *map; +} trans_table_t; + +static gchar * +trans_x264_val(trans_table_t *trans, char *val) +{ + int ii; + + if (val == NULL) + return NULL; + for (ii = 0; ii < trans->count; ii++) + { + if (strcmp(val, trans->map[ii].x264_val) == 0) + { + return trans->map[ii].ui_val; + } + } + return NULL; +} + +static gchar * +trans_ui_val(trans_table_t *trans, char *val) +{ + int ii; + + if (val == NULL) + return NULL; + for (ii = 0; ii < trans->count; ii++) + { + if (strcmp(val, trans->map[ii].ui_val) == 0) + { + return trans->map[ii].x264_val; + } + } + return NULL; +} + struct x264_opt_map_s { gchar **opt_syns; gchar *name; gchar *def_val; gint type; + trans_table_t *translation; gboolean found; }; static gchar *x264_ref_syns[] = {"ref", "frameref", NULL}; -static gchar *x264_mixed_syns[] = {"mixed-refs", "mixed_refs", NULL}; static gchar *x264_bframes_syns[] = {"bframes", NULL}; static gchar *x264_badapt_syns[] = {"b-adapt", "b_adapt", NULL}; static gchar *x264_direct_syns[] = {"direct", "direct-pred", "direct_pred", NULL}; -static gchar *x264_weightb_syns[] = {"weightb", "weight-b", "weight_b", NULL}; +static gchar *x264_weightp_syns[] = {"weightp", NULL}; static gchar *x264_bpyramid_syns[] = {"b-pyramid", "b_pyramid", NULL}; static gchar *x264_me_syns[] = {"me", NULL}; static gchar *x264_merange_syns[] = {"merange", "me-range", "me_range", NULL}; static gchar *x264_subme_syns[] = {"subme", "subq", NULL}; -static gchar *x264_analyse_syns[] = {"analyse", "partitions", NULL}; +static gchar *x264_aqmode_syns[] = {"aq-mode", NULL}; +static gchar *x264_analyse_syns[] = {"partitions", "analyse", 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", "no_fast_pskip", NULL}; static gchar *x264_psy_syns[] = {"psy-rd", "psy_rd", NULL}; +static gchar *x264_aq_strength_syns[] = {"aq-strength", "aq_strength", NULL}; +static gchar *x264_mbtree_syns[] = {"mbtree", NULL}; static gchar *x264_decimate_syns[] = {"no-dct-decimate", "no_dct_decimate", NULL}; static gchar *x264_cabac_syns[] = {"cabac", NULL}; @@ -170,26 +259,28 @@ find_syn_match(const gchar *opt, gchar **syns) 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_ref_syns, "x264_refs", "3", X264_OPT_INT}, + {x264_bframes_syns, "x264_bframes", "3", X264_OPT_INT}, {x264_direct_syns, "x264_direct", "spatial", X264_OPT_COMBO}, {x264_badapt_syns, "x264_b_adapt", "1", X264_OPT_COMBO}, - {x264_weightb_syns, "x264_weighted_bframes", "0", X264_OPT_BOOL}, - {x264_bpyramid_syns, "x264_bpyramid", "0", X264_OPT_BOOL}, + {x264_weightp_syns, "x264_weighted_pframes", "2", X264_OPT_COMBO}, + {x264_bpyramid_syns, "x264_bpyramid", "normal", X264_OPT_COMBO}, {x264_me_syns, "x264_me", "hex", X264_OPT_COMBO}, {x264_merange_syns, "x264_merange", "16", X264_OPT_INT}, - {x264_subme_syns, "x264_subme", "6", X264_OPT_COMBO}, - {x264_analyse_syns, "x264_analyse", "some", X264_OPT_COMBO}, - {x264_8x8dct_syns, "x264_8x8dct", "0", X264_OPT_BOOL}, + {x264_subme_syns, "x264_subme", "7", X264_OPT_COMBO}, + {x264_aqmode_syns, "x264_aqmode", "1", X264_OPT_INT_NONE}, + {x264_analyse_syns, "x264_analyse", "p8x8,b8x8,i8x8,i4x4", X264_OPT_COMBO}, + {x264_8x8dct_syns, "x264_8x8dct", "1", 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_trellis_syns, "x264_trellis", "1", 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}, + {x264_aq_strength_syns, "x264_aq_strength", "1", X264_OPT_DOUBLE}, {x264_psy_syns, "x264_psy_rd", "1,0", X264_OPT_PSY}, {x264_psy_syns, "x264_psy_trell", "1,0", X264_OPT_PSY}, + {x264_mbtree_syns, "x264_mbtree", "1", X264_OPT_BOOL_NONE}, }; #define X264_OPT_MAP_SIZE (sizeof(x264_opt_map)/sizeof(struct x264_opt_map_s)) @@ -208,6 +299,16 @@ x264_opt_get_default(const gchar *opt) } static void +x264_update_double(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + gdouble dval; + + if (val == NULL) return; + dval = g_strtod (val, NULL); + ghb_ui_update(ud, name, ghb_double_value(dval)); +} + +static void x264_update_int(signal_user_data_t *ud, const gchar *name, const gchar *val) { gint ival; @@ -217,6 +318,17 @@ x264_update_int(signal_user_data_t *ud, const gchar *name, const gchar *val) ghb_ui_update(ud, name, ghb_int64_value(ival)); } +static void +x264_update_int_setting(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + gint ival; + + if (val == NULL) return; + ival = g_strtod (val, NULL); + ghb_settings_set_value(ud->settings, name, ghb_int64_value(ival)); + ghb_check_dependency(ud, NULL, name); +} + static gchar *true_str[] = { "true", @@ -247,6 +359,17 @@ x264_update_bool(signal_user_data_t *ud, const gchar *name, const gchar *val) } static void +x264_update_bool_setting(signal_user_data_t *ud, const gchar *name, const gchar *val) +{ + if (val == NULL) + ghb_settings_set_value(ud->settings, name, ghb_boolean_value(1)); + else + ghb_settings_set_value(ud->settings, name, ghb_boolean_value(str_is_true(val))); + + ghb_check_dependency(ud, NULL, name); +} + +static void x264_update_combo(signal_user_data_t *ud, const gchar *name, const gchar *val) { GtkTreeModel *store; @@ -369,6 +492,31 @@ x264_update_psy(signal_user_data_t *ud, const gchar *xval) ghb_ui_update(ud, "x264_psy_trell", ghb_double_value(trell_value)); } +static void do_update(signal_user_data_t *ud, char *name, gint type, char *val) +{ + switch(type) + { + case X264_OPT_INT: + x264_update_int(ud, name, val); + break; + case X264_OPT_DOUBLE: + x264_update_double(ud, name, val); + break; + case X264_OPT_BOOL: + x264_update_bool(ud, name, val); + break; + case X264_OPT_COMBO: + x264_update_combo(ud, name, val); + break; + case X264_OPT_BOOL_NONE: + x264_update_bool_setting(ud, name, val); + break; + case X264_OPT_INT_NONE: + x264_update_int_setting(ud, name, val); + break; + } +} + void ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) { @@ -400,6 +548,9 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) case X264_OPT_INT: x264_update_int(ud, x264_opt_map[jj].name, val); break; + case X264_OPT_DOUBLE: + x264_update_double(ud, x264_opt_map[jj].name, val); + break; case X264_OPT_BOOL: x264_update_bool(ud, x264_opt_map[jj].name, val); break; @@ -416,6 +567,27 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) x264_opt_map[jj+1].found = TRUE; x264_update_psy(ud, val); break; + case X264_OPT_BOOL_NONE: + x264_update_bool_setting(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_INT_NONE: + x264_update_int_setting(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_TRANS: + if (x264_opt_map[jj].translation == NULL) + break; + val = trans_x264_val(x264_opt_map[jj].translation, val); + if (val != NULL) + { + do_update(ud, x264_opt_map[jj].name, + x264_opt_map[jj].translation->ui_type, val); + // TODO un-grey the ui control + } + else + { + // TODO grey out the ui control + } + break; } break; } @@ -433,6 +605,9 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) case X264_OPT_INT: x264_update_int(ud, x264_opt_map[jj].name, val); break; + case X264_OPT_DOUBLE: + x264_update_double(ud, x264_opt_map[jj].name, val); + break; case X264_OPT_BOOL: x264_update_bool(ud, x264_opt_map[jj].name, val); break; @@ -445,6 +620,27 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) case X264_OPT_PSY: x264_update_psy(ud, val); break; + case X264_OPT_BOOL_NONE: + x264_update_bool_setting(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_INT_NONE: + x264_update_int_setting(ud, x264_opt_map[jj].name, val); + break; + case X264_OPT_TRANS: + if (x264_opt_map[jj].translation == NULL) + break; + val = g_strdup(trans_x264_val(x264_opt_map[jj].translation, val)); + if (val != NULL) + { + do_update(ud, x264_opt_map[jj].name, + x264_opt_map[jj].translation->ui_type, val); + // TODO un-grey the ui control + } + else + { + // TODO grey out the ui control + } + break; } x264_opt_map[jj].found = TRUE; g_free(val); @@ -481,10 +677,11 @@ static void x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) { gint jj; - const gchar *name = gtk_widget_get_name(widget); + const gchar *name = ghb_get_setting_key(widget); gchar **opt_syns = NULL; const gchar *def_val = NULL; gint type; + trans_table_t *trans; for (jj = 0; jj < X264_OPT_MAP_SIZE; jj++) { @@ -494,6 +691,7 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) opt_syns = x264_opt_map[jj].opt_syns; def_val = x264_opt_map[jj].def_val; type = x264_opt_map[jj].type; + trans = x264_opt_map[jj].translation; break; } } @@ -547,6 +745,16 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) } ghb_value_free(gval); } + if (type == X264_OPT_TRANS) + { + gchar *tmp; + tmp = g_strdup(trans_ui_val(trans, val)); + if (tmp) + { + g_free(val); + val = tmp; + } + } if (strcmp(def_val, val) != 0) { g_string_append_printf(x264opts, "%s=%s:", opt_syns[syn], val); @@ -584,6 +792,16 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) } ghb_value_free(gval); } + if (type == X264_OPT_TRANS) + { + gchar *tmp; + tmp = g_strdup(trans_ui_val(trans, val)); + if (tmp) + { + g_free(val); + val = tmp; + } + } if (strcmp(def_val, val) != 0) { g_string_append_printf(x264opts, "%s=%s:", opt_syns[0], val); @@ -651,6 +869,122 @@ x264_remove_opt(gchar **opts, gchar **opt_syns) } } +static gchar* +x264_lookup_value(gchar **opts, gchar **opt_syns) +{ + gchar *ret = NULL; + gint pos; + + const gchar *def_val = x264_opt_get_default(opt_syns[0]); + + pos = x264_find_opt(opts, opt_syns); + if (pos >= 0) + { + gchar *cpos = strchr(opts[pos], '='); + if (cpos != NULL) + { + ret = g_strdup(cpos+1); + } + else + { + ret = g_strdup(""); + } + } + else if (def_val != NULL) + { + ret = g_strdup(def_val); + } + return ret; +} + +gint +ghb_lookup_badapt(const gchar *options) +{ + gint ret = 0; + gchar *result; + gchar **split; + + if (options == NULL) + options = ""; + + split = g_strsplit(options, ":", -1); + + result = x264_lookup_value(split, x264_badapt_syns); + g_strfreev(split); + if (result != NULL) + { + ret = g_strtod(result, NULL); + g_free(result); + } + return ret; +} + +gint +ghb_lookup_aqmode(const gchar *options) +{ + gint ret = 0; + gchar *result; + gchar **split; + + if (options == NULL) + options = ""; + + split = g_strsplit(options, ":", -1); + + result = x264_lookup_value(split, x264_aqmode_syns); + g_strfreev(split); + if (result != NULL) + { + ret = g_strtod(result, NULL); + g_free(result); + } + return ret; +} + +gint +ghb_lookup_bframes(const gchar *options) +{ + gint ret = 0; + gchar *result; + gchar **split; + + if (options == NULL) + options = ""; + + split = g_strsplit(options, ":", -1); + + result = x264_lookup_value(split, x264_bframes_syns); + g_strfreev(split); + if (result != NULL) + { + ret = g_strtod(result, NULL); + g_free(result); + } + return ret; +} + +gint +ghb_lookup_mbtree(const gchar *options) +{ + gint ret = ghb_lookup_bframes(options) != 0; + gchar *result; + gchar **split; + + if (options == NULL) + options = ""; + + split = g_strsplit(options, ":", -1); + + result = x264_lookup_value(split, x264_mbtree_syns); + g_strfreev(split); + if (result != NULL) + { + ret = g_strtod(result, NULL); + g_free(result); + } + return ret; +} + // Construct the x264 options string // The result is allocated, so someone must free it at some point. static gchar* @@ -667,6 +1001,16 @@ sanitize_x264opts(signal_user_data_t *ud, const gchar *options) x264_remove_opt(split, x264_psy_syns); } gint trell = ghb_settings_combo_int(ud->settings, "x264_trellis"); + if (subme == 10) + { + gint aqmode = ghb_lookup_aqmode(options); + if (trell != 2 || aqmode == 0) + { + gint pos = x264_find_opt(split, x264_subme_syns); + g_free(split[pos]); + split[pos] = g_strdup_printf("subme=9"); + } + } if (trell < 1) { gint psy; @@ -684,15 +1028,9 @@ sanitize_x264opts(signal_user_data_t *ud, const gchar *options) split[psy] = g_strdup_printf("psy-rd=%g,0", psy_rd); } } - gint refs = ghb_settings_get_int(ud->settings, "x264_refs"); - if (refs <= 1) - { - x264_remove_opt(split, x264_mixed_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_direct_syns); x264_remove_opt(split, x264_badapt_syns); } @@ -700,10 +1038,6 @@ sanitize_x264opts(signal_user_data_t *ud, const gchar *options) { x264_remove_opt(split, x264_bpyramid_syns); } - if (!ghb_settings_get_boolean(ud->settings, "x264_cabac")) - { - x264_remove_opt(split, x264_trellis_syns); - } // Remove entries that match the defaults for (ii = 0; split[ii] != NULL; ii++) { @@ -719,7 +1053,8 @@ sanitize_x264opts(signal_user_data_t *ud, const gchar *options) { val = "1"; } - const gchar *def_val = x264_opt_get_default(opt); + const gchar *def_val; + def_val = x264_opt_get_default(opt); if (strcmp(val, def_val) == 0) { // Matches the default, so remove it