X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=gtk%2Fsrc%2Fx264handler.c;h=61adaa0b020822e82d1f9fe0a8d07945415e4869;hb=0884cb45aeeb60a46effe1d1056a61fe68300ea7;hp=8f8576c94efb203bb71fa2e9c2264aed1ecbf7aa;hpb=4283033b2ded203900f2328b2692982b8bbe833d;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/gtk/src/x264handler.c b/gtk/src/x264handler.c index 8f8576c9..61adaa0b 100644 --- a/gtk/src/x264handler.c +++ b/gtk/src/x264handler.c @@ -17,15 +17,17 @@ #include "values.h" #include "callbacks.h" #include "presets.h" +#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); @@ -35,11 +37,39 @@ 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_me_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + gint me; + + ghb_widget_to_setting(ud->settings, widget); + 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); + widget = GHB_WIDGET(ud->builder, "x264_merange"); + me = ghb_settings_combo_int(ud->settings, "x264_me"); + if (me < 2) + { // me < umh + // me_range 4 - 16 + gtk_spin_button_set_range(GTK_SPIN_BUTTON(widget), 4, 16); + } + else + { + // me_range 4 - 64 + gtk_spin_button_set_range(GTK_SPIN_BUTTON(widget), 4, 64); + } +} + +G_MODULE_EXPORT void x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { g_debug("x264_entry_changed_cb ()"); @@ -48,9 +78,9 @@ x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud) GtkWidget *textview; gchar *options; - textview = GTK_WIDGET(GHB_WIDGET(ud->builder, "x264_options")); + textview = GTK_WIDGET(GHB_WIDGET(ud->builder, "x264Option")); ghb_widget_to_setting(ud->settings, textview); - options = ghb_settings_get_string(ud->settings, "x264_options"); + options = ghb_settings_get_string(ud->settings, "x264Option"); ignore_options_update = TRUE; ghb_x264_parse_options(ud, options); if (!GTK_WIDGET_HAS_FOCUS(textview)) @@ -58,7 +88,7 @@ x264_entry_changed_cb(GtkWidget *widget, signal_user_data_t *ud) gchar *sopts; sopts = sanitize_x264opts(ud, options); - ghb_ui_update(ud, "x264_options", ghb_string_value(sopts)); + ghb_ui_update(ud, "x264Option", ghb_string_value(sopts)); ghb_x264_parse_options(ud, sopts); g_free(sopts); } @@ -67,19 +97,19 @@ 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) { gchar *options, *sopts; ghb_widget_to_setting(ud->settings, widget); - options = ghb_settings_get_string(ud->settings, "x264_options"); + options = ghb_settings_get_string(ud->settings, "x264Option"); sopts = sanitize_x264opts(ud, options); ignore_options_update = TRUE; - if (sopts != NULL) + if (sopts != NULL && strcmp(sopts, options) != 0) { - ghb_ui_update(ud, "x264_options", ghb_string_value(sopts)); + ghb_ui_update(ud, "x264Option", ghb_string_value(sopts)); ghb_x264_parse_options(ud, sopts); } g_free(options); @@ -90,7 +120,11 @@ 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_COMBO, X264_OPT_BOOL, @@ -108,20 +142,22 @@ struct x264_opt_map_s 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_brdo_syns[] = {"brdo", "b-rdo", "b_rdo", NULL}; -static gchar *x264_bime_syns[] = {"bime", 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_aqmode_syns[] = {"aq-mode", 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", "no_fast_pskip", NULL}; +static gchar *x264_psy_syns[] = {"psy-rd", "psy_rd", 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}; @@ -140,25 +176,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_mixed_syns, "x264_mixed_refs", "1", X264_OPT_BOOL}, + {x264_bframes_syns, "x264_bframes", "3", 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_badapt_syns, "x264_b_adapt", "1", X264_OPT_COMBO}, + {x264_weightb_syns, "x264_weighted_bframes", "1", 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", "6", X264_OPT_COMBO}, + {x264_subme_syns, "x264_subme", "7", X264_OPT_COMBO}, + {x264_aqmode_syns, "x264_aqmode", "1", X264_OPT_INT_NONE}, {x264_analyse_syns, "x264_analyse", "some", X264_OPT_COMBO}, - {x264_8x8dct_syns, "x264_8x8dct", "0", X264_OPT_BOOL}, + {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_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)) @@ -186,6 +225,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", @@ -216,12 +266,23 @@ 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; GtkTreeIter iter; gchar *shortOpt; - gint ivalue; + gdouble ivalue; gboolean foundit = FALSE; GtkWidget *widget; @@ -302,6 +363,42 @@ x264_update_deblock(signal_user_data_t *ud, const gchar *xval) ghb_ui_update(ud, "x264_deblock_beta", ghb_int64_value(bvalue)); } +static void +x264_parse_psy(const gchar *psy, gdouble *psy_rd, gdouble *psy_trell) +{ + gchar *val; + gchar *trell_val = NULL; + gchar *end; + + *psy_rd = 0.; + *psy_trell = 0.; + if (psy == NULL) return; + val = g_strdup(psy); + gchar *pos = strchr(val, ','); + if (pos != NULL) + { + trell_val = pos + 1; + *pos = 0; + } + *psy_rd = g_strtod (val, &end); + if (trell_val != NULL) + { + *psy_trell = g_strtod (trell_val, &end); + } + g_free(val); +} + +static void +x264_update_psy(signal_user_data_t *ud, const gchar *xval) +{ + gdouble rd_value, trell_value; + + if (xval == NULL) return; + x264_parse_psy(xval, &rd_value, &trell_value); + ghb_ui_update(ud, "x264_psy_rd", ghb_double_value(rd_value)); + ghb_ui_update(ud, "x264_psy_trell", ghb_double_value(trell_value)); +} + void ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) { @@ -344,6 +441,17 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) x264_opt_map[jj+1].found = TRUE; x264_update_deblock(ud, val); break; + case X264_OPT_PSY: + // dirty little hack. mark psy_trell found as well + 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; } break; } @@ -370,6 +478,15 @@ ghb_x264_parse_options(signal_user_data_t *ud, const gchar *options) case X264_OPT_DEBLOCK: x264_update_deblock(ud, val); break; + 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; } x264_opt_map[jj].found = TRUE; g_free(val); @@ -391,11 +508,22 @@ get_deblock_val(signal_user_data_t *ud) return result; } +gchar* +get_psy_val(signal_user_data_t *ud) +{ + gdouble rd, trell; + gchar *result; + rd = ghb_settings_get_double(ud->settings, "x264_psy_rd"); + trell = ghb_settings_get_double(ud->settings, "x264_psy_trell"); + result = g_strdup_printf("%g,%g", rd, trell); + return result; +} + 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; @@ -419,7 +547,7 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) gint ii; gboolean foundit = FALSE; - options = ghb_settings_get_string(ud->settings, "x264_options"); + options = ghb_settings_get_string(ud->settings, "x264Option"); if (options) { split = g_strsplit(options, ":", -1); @@ -442,6 +570,8 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) foundit = TRUE; if (type == X264_OPT_DEBLOCK) val = get_deblock_val(ud); + else if (type == X264_OPT_PSY) + val = get_psy_val(ud); else { GValue *gval; @@ -477,6 +607,8 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) gchar *val; if (type == X264_OPT_DEBLOCK) val = get_deblock_val(ud); + else if (type == X264_OPT_PSY) + val = get_psy_val(ud); else { GValue *gval; @@ -509,13 +641,36 @@ x264_opt_update(signal_user_data_t *ud, GtkWidget *widget) if (len > 0) result[len - 1] = 0; gchar *sopts; sopts = sanitize_x264opts(ud, result); - ghb_ui_update(ud, "x264_options", ghb_string_value(sopts)); + ghb_ui_update(ud, "x264Option", ghb_string_value(sopts)); ghb_x264_parse_options(ud, sopts); g_free(sopts); g_free(result); } } +static gint +x264_find_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) + { + g_free(opt); + return ii; + } + g_free(opt); + } + return -1; +} + static void x264_remove_opt(gchar **opts, gchar **opt_syns) { @@ -538,6 +693,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* @@ -545,65 +816,86 @@ 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++) + + // Fix up option dependencies + gint subme = ghb_settings_combo_int(ud->settings, "x264_subme"); + if (subme < 6) { - gchar *val = NULL; - gchar *opt = g_strdup(split[ii]); - gchar *pos = strchr(opt, '='); - if (pos != NULL) - { - val = pos + 1; - *pos = 0; - } - else + 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) { - val = "1"; + gint pos = x264_find_opt(split, x264_subme_syns); + g_free(split[pos]); + split[pos] = g_strdup_printf("subme=9"); } - const gchar *def_val = x264_opt_get_default(opt); - if (strcmp(val, def_val) == 0) + } + if (trell < 1) + { + gint psy; + gdouble psy_rd = 0., psy_trell; + + psy = x264_find_opt(split, x264_psy_syns); + if (psy >= 0) { - // Matches the default, so remove it - split[ii][0] = 0; + gchar *pos = strchr(split[psy], '='); + if (pos != NULL) + { + x264_parse_psy(pos+1, &psy_rd, &psy_trell); + } + g_free(split[psy]); + split[psy] = g_strdup_printf("psy-rd=%g,0", psy_rd); } - 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; - - subme = ghb_settings_combo_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); x264_remove_opt(split, x264_direct_syns); + x264_remove_opt(split, x264_badapt_syns); } if (bframes <= 1) { x264_remove_opt(split, x264_bpyramid_syns); } - 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); - } - g_free(me); 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++) + { + 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; + 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); + } for (ii = 0; split[ii] != NULL; ii++) { if (split[ii][0] != 0)