OSDN Git Service

LinGui: fix aq-strength slider range. should be 0-2, not 0-1
[handbrake-jp/handbrake-jp-git.git] / gtk / src / hb-backend.c
index 78fab8c..63ce0c0 100644 (file)
@@ -287,6 +287,30 @@ combo_opts_t badapt_opts =
        d_badapt_opts
 };
 
+static options_map_t d_bpyramid_opts[] =
+{
+       {"Off",    "none",   0, "none"},
+       {"Strict", "strict", 1, "strict"},
+       {"Normal", "normal", 2, "normal"},
+};
+combo_opts_t bpyramid_opts =
+{
+       sizeof(d_bpyramid_opts)/sizeof(options_map_t),
+       d_bpyramid_opts
+};
+
+static options_map_t d_weightp_opts[] =
+{
+       {"Off",   "0", 0, "0"},
+       {"Blind", "1", 1, "1"},
+       {"Smart", "2", 2, "2"},
+};
+combo_opts_t weightp_opts =
+{
+       sizeof(d_weightp_opts)/sizeof(options_map_t),
+       d_weightp_opts
+};
+
 static options_map_t d_me_opts[] =
 {
        {"Diamond",              "dia",  0, "dia"},
@@ -303,16 +327,17 @@ combo_opts_t me_opts =
 
 static options_map_t d_subme_opts[] =
 {
-       {"1", "1", 1, "1"},
-       {"2", "2", 2, "2"},
-       {"3", "3", 3, "3"},
-       {"4", "4", 4, "4"},
-       {"5", "5", 5, "5"},
-       {"6", "6", 6, "6"},
-       {"7", "7", 7, "7"},
-       {"8", "8", 8, "8"},
-       {"9", "9", 9, "9"},
-       {"10", "10", 10, "10"},
+       {"0: SAD, no subpel",          "0", 0, "0"},
+       {"1: SAD, qpel",               "1", 1, "1"},
+       {"2: SATD, qpel",              "2", 2, "2"},
+       {"3: SATD: multi-qpel",        "3", 3, "3"},
+       {"4: SATD, qpel on all",       "4", 4, "4"},
+       {"5: SATD, multi-qpel on all", "5", 5, "5"},
+       {"6: RD in I/P-frames",        "6", 6, "6"},
+       {"7: RD in all frames",        "7", 7, "7"},
+       {"8: RD refine in I/P-frames", "8", 8, "8"},
+       {"9: RD refine in all frames", "9", 9, "9"},
+       {"10: QPRD in all frames",     "10", 10, "10"},
 };
 combo_opts_t subme_opts =
 {
@@ -322,10 +347,11 @@ combo_opts_t subme_opts =
 
 static options_map_t d_analyse_opts[] =
 {
-       {"Some", "some", 0, "some"},
+       {"Most", "p8x8,b8x8,i8x8,i4x4", 0, "p8x8,b8x8,i8x8,i4x4"},
        {"None", "none", 1, "none"},
-       {"All",  "all",  2, "all"},
-       {"Custom",  "custom",  3, "all"},
+       {"Some", "i4x4,i8x8", 2, "i4x4,i8x8"},
+       {"All",  "all",  3, "all"},
+       {"Custom",  "custom",  4, "all"},
 };
 combo_opts_t analyse_opts =
 {
@@ -335,9 +361,9 @@ combo_opts_t analyse_opts =
 
 static options_map_t d_trellis_opts[] =
 {
-       {"Disabled",          "0", 0, "0"},
-       {"Final Macro Block", "1", 1, "1"},
-       {"Always",            "2", 2, "2"},
+       {"Off",         "0", 0, "0"},
+       {"Encode only", "1", 1, "1"},
+       {"Always",      "2", 2, "2"},
 };
 combo_opts_t trellis_opts =
 {
@@ -388,6 +414,8 @@ combo_name_map_t combo_name_map[] =
        {"AudioEncoder", &acodec_opts},
        {"x264_direct", &direct_opts},
        {"x264_b_adapt", &badapt_opts},
+       {"x264_bpyramid", &bpyramid_opts},
+       {"x264_weighted_pframes", &weightp_opts},
        {"x264_me", &me_opts},
        {"x264_subme", &subme_opts},
        {"x264_analyse", &analyse_opts},
@@ -731,23 +759,67 @@ ghb_vquality_range(
        }
 }
 
+gint
+find_combo_entry(combo_opts_t *opts, const GValue *gval)
+{
+       gint ii;
+
+       if (G_VALUE_TYPE(gval) == G_TYPE_STRING)
+       {
+               gchar *str;
+               str = ghb_value_string(gval);
+               for (ii = 0; ii < opts->count; ii++)
+               {
+                       if (strcmp(opts->map[ii].shortOpt, str) == 0)
+                       {
+                               break;
+                       }
+               }
+               g_free(str);
+               return ii;
+       }
+       else if (G_VALUE_TYPE(gval) == G_TYPE_DOUBLE)
+       {
+               gdouble val;
+               val = ghb_value_double(gval);
+               for (ii = 0; ii < opts->count; ii++)
+               {
+                       if (opts->map[ii].ivalue == val)
+                       {
+                               break;
+                       }
+               }
+               return ii;
+       }
+       else if (G_VALUE_TYPE(gval) == G_TYPE_INT ||
+                        G_VALUE_TYPE(gval) == G_TYPE_BOOLEAN ||
+                        G_VALUE_TYPE(gval) == G_TYPE_INT64)
+       {
+               gint64 val;
+               val = ghb_value_int64(gval);
+               for (ii = 0; ii < opts->count; ii++)
+               {
+                       if ((gint64)opts->map[ii].ivalue == val)
+                       {
+                               break;
+                       }
+               }
+               return ii;
+       }
+       return opts->count;
+}
+
 static const gchar*
 lookup_generic_string(combo_opts_t *opts, const GValue *gval)
 {
        gint ii;
-       gchar *str;
        const gchar *result = "";
 
-       str = ghb_value_string(gval);
-       for (ii = 0; ii < opts->count; ii++)
+       ii = find_combo_entry(opts, gval);
+       if (ii < opts->count)
        {
-               if (strcmp(opts->map[ii].shortOpt, str) == 0)
-               {
-                       result = opts->map[ii].svalue;
-                       break;
-               }
+               result = opts->map[ii].svalue;
        }
-       g_free(str);
        return result;
 }
 
@@ -755,19 +827,13 @@ static gint
 lookup_generic_int(combo_opts_t *opts, const GValue *gval)
 {
        gint ii;
-       gchar *str;
        gint result = -1;
 
-       str = ghb_value_string(gval);
-       for (ii = 0; ii < opts->count; ii++)
+       ii = find_combo_entry(opts, gval);
+       if (ii < opts->count)
        {
-               if (strcmp(opts->map[ii].shortOpt, str) == 0)
-               {
-                       result = opts->map[ii].ivalue;
-                       break;
-               }
+               result = opts->map[ii].ivalue;
        }
-       g_free(str);
        return result;
 }
 
@@ -775,19 +841,13 @@ static gdouble
 lookup_generic_double(combo_opts_t *opts, const GValue *gval)
 {
        gint ii;
-       gchar *str;
        gdouble result = -1;
 
-       str = ghb_value_string(gval);
-       for (ii = 0; ii < opts->count; ii++)
+       ii = find_combo_entry(opts, gval);
+       if (ii < opts->count)
        {
-               if (strcmp(opts->map[ii].shortOpt, str) == 0)
-               {
-                       result = opts->map[ii].ivalue;
-                       break;
-               }
+               result = opts->map[ii].ivalue;
        }
-       g_free(str);
        return result;
 }
 
@@ -795,19 +855,13 @@ static const gchar*
 lookup_generic_option(combo_opts_t *opts, const GValue *gval)
 {
        gint ii;
-       gchar *str;
        const gchar *result = "";
 
-       str = ghb_value_string(gval);
-       for (ii = 0; ii < opts->count; ii++)
+       ii = find_combo_entry(opts, gval);
+       if (ii < opts->count)
        {
-               if (strcmp(opts->map[ii].shortOpt, str) == 0)
-               {
-                       result = opts->map[ii].option;
-                       break;
-               }
+               result = opts->map[ii].option;
        }
-       g_free(str);
        return result;
 }
 
@@ -815,20 +869,36 @@ static gint
 lookup_mix_int(const GValue *mix)
 {
        gint ii;
-       gchar *str;
        gint result = 0;
 
 
-       str = ghb_value_string(mix);
-       for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+       if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+               gchar * str = ghb_value_string(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
                {
-                       result = hb_audio_mixdowns[ii].amixdown;
-                       break;
+                       if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+                       {
+                               result = hb_audio_mixdowns[ii].amixdown;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
+                        G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
+       {
+               gint val = ghb_value_int(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+               {
+                       if (hb_audio_mixdowns[ii].amixdown == val)
+                       {
+                               result = hb_audio_mixdowns[ii].amixdown;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -836,20 +906,73 @@ static const gchar*
 lookup_mix_option(const GValue *mix)
 {
        gint ii;
-       gchar *str;
        gchar *result = "None";
 
 
-       str = ghb_value_string(mix);
-       for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+       if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+               gchar *str = ghb_value_string(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
                {
-                       result = hb_audio_mixdowns[ii].human_readable_name;
-                       break;
+                       if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+                       {
+                               result = hb_audio_mixdowns[ii].human_readable_name;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
+                        G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
+       {
+               gint val = ghb_value_int(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+               {
+                       if (hb_audio_mixdowns[ii].amixdown == val)
+                       {
+                               result = hb_audio_mixdowns[ii].human_readable_name;
+                               break;
+                       }
+               }
+       }
+       return result;
+}
+
+static const gchar*
+lookup_mix_string(const GValue *mix)
+{
+       gint ii;
+       gchar *result = "None";
+
+
+       if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
+       {
+               gchar *str = ghb_value_string(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+               {
+                       if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+                       {
+                               result = hb_audio_mixdowns[ii].short_name;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
+                        G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
+       {
+               gint val = ghb_value_int(mix);
+               for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+               {
+                       if (hb_audio_mixdowns[ii].amixdown == val)
+                       {
+                               result = hb_audio_mixdowns[ii].short_name;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -899,21 +1022,37 @@ static gint
 lookup_audio_rate_int(const GValue *rate)
 {
        gint ii;
-       gchar *str;
        gint result = 0;
 
-       // Coincidentally, the string "source" will return 0
-       // which is our flag to use "same as source"
-       str = ghb_value_string(rate);
-       for (ii = 0; ii < hb_audio_rates_count; ii++)
+       if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_rates[ii].string, str) == 0)
+               // Coincidentally, the string "source" will return 0
+               // which is our flag to use "same as source"
+               gchar * str = ghb_value_string(rate);
+               for (ii = 0; ii < hb_audio_rates_count; ii++)
                {
-                       result = hb_audio_rates[ii].rate;
-                       break;
+                       if (strcmp(hb_audio_rates[ii].string, str) == 0)
+                       {
+                               result = hb_audio_rates[ii].rate;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
+                        G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+       {
+               for (ii = 0; ii < hb_audio_rates_count; ii++)
+               {
+                       gint val = ghb_value_int(rate);
+                       if (val == hb_audio_rates[ii].rate)
+                       {
+                               result = hb_audio_rates[ii].rate;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -921,21 +1060,37 @@ static const gchar*
 lookup_audio_rate_option(const GValue *rate)
 {
        gint ii;
-       gchar *str;
        const gchar *result = "Same as source";
 
-       // Coincidentally, the string "source" will return 0
-       // which is our flag to use "same as source"
-       str = ghb_value_string(rate);
-       for (ii = 0; ii < hb_audio_rates_count; ii++)
+       if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_rates[ii].string, str) == 0)
+               // Coincidentally, the string "source" will return 0
+               // which is our flag to use "same as source"
+               gchar *str = ghb_value_string(rate);
+               for (ii = 0; ii < hb_audio_rates_count; ii++)
                {
-                       result = hb_audio_rates[ii].string;
-                       break;
+                       if (strcmp(hb_audio_rates[ii].string, str) == 0)
+                       {
+                               result = hb_audio_rates[ii].string;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
+                        G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+       {
+               for (ii = 0; ii < hb_audio_rates_count; ii++)
+               {
+                       gint val = ghb_value_int(rate);
+                       if (val == hb_audio_rates[ii].rate)
+                       {
+                               result = hb_audio_rates[ii].string;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -948,7 +1103,7 @@ ghb_find_closest_audio_bitrate(gint codec, gint rate)
        gint result;
 
        if (codec == HB_ACODEC_FAAC)
-               high = 160;
+               high = 320;
 
        result = high;
        for (ii = 0; ii < hb_audio_bitrates_count; ii++)
@@ -970,21 +1125,37 @@ static gint
 lookup_audio_bitrate_int(const GValue *rate)
 {
        gint ii;
-       gchar *str;
        gint result = 0;
 
-       // Coincidentally, the string "source" will return 0
-       // which is our flag to use "same as source"
-       str = ghb_value_string(rate);
-       for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+       if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
+               // Coincidentally, the string "source" will return 0
+               // which is our flag to use "same as source"
+               gchar *str = ghb_value_string(rate);
+               for (ii = 0; ii < hb_audio_bitrates_count; ii++)
                {
-                       result = hb_audio_bitrates[ii].rate;
-                       break;
+                       if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
+                       {
+                               result = hb_audio_bitrates[ii].rate;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
+                        G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+       {
+               gint val = ghb_value_int(rate);
+               for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+               {
+                       if (hb_audio_bitrates[ii].rate == val)
+                       {
+                               result = hb_audio_bitrates[ii].rate;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -992,21 +1163,37 @@ static const gchar*
 lookup_audio_bitrate_option(const GValue *rate)
 {
        gint ii;
-       gchar *str;
        const gchar *result = "Same as source";
 
-       // Coincidentally, the string "source" will return 0
-       // which is our flag to use "same as source"
-       str = ghb_value_string(rate);
-       for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+       if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
        {
-               if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
+               // Coincidentally, the string "source" will return 0
+               // which is our flag to use "same as source"
+               gchar *str = ghb_value_string(rate);
+               for (ii = 0; ii < hb_audio_bitrates_count; ii++)
                {
-                       result = hb_audio_bitrates[ii].string;
-                       break;
+                       if (strcmp(hb_audio_bitrates[ii].string, str) == 0)
+                       {
+                               result = hb_audio_bitrates[ii].string;
+                               break;
+                       }
+               }
+               g_free(str);
+       }
+       else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
+                        G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
+                        G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+       {
+               gint val = ghb_value_int(rate);
+               for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+               {
+                       if (hb_audio_bitrates[ii].rate == val)
+                       {
+                               result = hb_audio_bitrates[ii].string;
+                               break;
+                       }
                }
        }
-       g_free(str);
        return result;
 }
 
@@ -1068,9 +1255,10 @@ ghb_lookup_acodec_value(gint val)
                if ((int)acodec_opts.map[ii].ivalue == val)
                {
                        value = ghb_string_value_new(acodec_opts.map[ii].shortOpt);
-                       break;
+                       return value;
                }
        }
+       value = ghb_string_value_new("auto");
        return value;
 }
 
@@ -1149,6 +1337,37 @@ ghb_subtitle_track_source(signal_user_data_t *ud, gint track)
 }
 
 const char*
+ghb_subtitle_source_name(gint source)
+{
+       const gchar * name = "Unknown";
+       switch (source)
+       {
+               case VOBSUB:
+                       name = "VOBSUB";
+                       break;
+               case TX3GSUB:
+                       name = "TX3G";
+                       break;
+               case UTF8SUB:
+                       name = "UTF8";
+                       break;
+               case CC708SUB:
+               case CC608SUB:
+                       name = "CC";
+                       break;
+               case SRTSUB:
+                       name = "SRT";
+                       break;
+               case SSASUB:
+                       name = "SSA";
+                       break;
+               default:
+                       break;
+       }
+       return name;
+}
+
+const char*
 ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track)
 {
        gint titleindex;
@@ -1186,21 +1405,7 @@ ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track)
        sub = hb_list_item( title->list_subtitle, track);
        if (sub != NULL)
        {
-               switch (sub->source)
-               {
-                       case VOBSUB:
-                               name = "Bitmap";
-                               break;
-                       case CC708SUB:
-                       case CC608SUB:
-                               name = "Text";
-                               break;
-                       case SRTSUB:
-                               name = "SRT";
-                               break;
-                       default:
-                               break;
-               }
+               name = ghb_subtitle_source_name(sub->source);
        }
 
 done:
@@ -1350,7 +1555,7 @@ ghb_grey_combo_options(GtkBuilder *builder)
        container = ghb_lookup_combo_int("FileFormat", gval);
        ghb_value_free(gval);
 
-       grey_combo_box_item(builder, "x264_analyse", 3, TRUE);
+       grey_combo_box_item(builder, "x264_analyse", 4, TRUE);
        grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, FALSE);
        grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_LAME, FALSE);
        grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, FALSE);
@@ -1393,7 +1598,7 @@ ghb_grey_combo_options(GtkBuilder *builder)
        gboolean allow_dolby = TRUE;
        gboolean allow_dpl2 = TRUE;
        gboolean allow_6ch = TRUE;
-       allow_mono = acodec & ~HB_ACODEC_LAME;
+       allow_mono = TRUE;
        allow_6ch = acodec & ~HB_ACODEC_LAME;
        if (audio)
        {
@@ -1421,7 +1626,12 @@ ghb_get_best_audio_bitrate(gint acodec, gint br, gint channels)
 {
        if (acodec & HB_ACODEC_FAAC)
        {
-       int maxbr = channels * 80;
+               int maxbr;
+
+               if (channels == 2)
+                       maxbr = 320;
+               else
+                       maxbr = 768;
                if (br > maxbr)
                        br = maxbr;
        }
@@ -1446,7 +1656,7 @@ ghb_get_best_mix(gint titleindex, gint track, gint acodec, gint mix)
        audio = get_hb_audio(titleindex, track);
        if (audio)
        {
-               allow_mono = (acodec & ~HB_ACODEC_LAME);
+               allow_mono = TRUE;
                gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
                allow_stereo =
                        ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
@@ -1961,7 +2171,18 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
                        subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
                        // Skip subtitles that must be burned if there is already
                        // a burned subtitle in the list
-                       options[ii] = g_strdup_printf("%d - %s", ii+1, subtitle->lang);
+#if 0
+                       if (subtitle->source == VOBSUB)
+                       {
+                               options[ii] = g_strdup_printf("%d - %s", ii+1, subtitle->lang);
+                       }
+                       else
+#endif
+                       {
+                               options[ii] = g_strdup_printf("%d - %s (%s)", ii+1, 
+                                       subtitle->lang, 
+                                       ghb_subtitle_source_name(subtitle->source));
+                       }
                        subtitle_opts.map[ii+1].option = options[ii];
                        subtitle_opts.map[ii+1].shortOpt = index_str[ii];
                        subtitle_opts.map[ii+1].ivalue = ii;
@@ -2012,21 +2233,23 @@ ghb_longest_title()
        hb_title_t * title;
        gint ii;
        gint count = 0;
-       guint64 longest = 0;
        gint titleindex = 0;
+       gint feature;
        
        g_debug("ghb_longest_title ()\n");
        if (h_scan == NULL) return 0;
        list = hb_get_titles( h_scan );
        count = hb_list_count( list );
        if (count > 100) count = 100;
+       if (count < 1) return 0;
+       title = (hb_title_t*)hb_list_item(list, 0);
+       feature = title->job->feature;
        for (ii = 0; ii < count; ii++)
        {
                title = (hb_title_t*)hb_list_item(list, ii);
-               if (title->duration > longest)
+               if (title->index == feature)
                {
-                       titleindex = ii;
-                       longest = title->duration;
+                       return ii;
                }
        }
        return titleindex;
@@ -2090,12 +2313,13 @@ ghb_find_audio_track(
        gint ii;
        gint count = 0;
        gint track = -1;
-       gint max_chan = 0;
-       gboolean *used;
+       gint max_chan;
+       gboolean *used = NULL;
        gboolean *passthru_used;
        gint try_acodec;
        gint passthru_acodec;
        gboolean passthru;
+       gint channels;
        
        g_debug("find_audio_track ()\n");
        if (h_scan == NULL) return -1;
@@ -2108,13 +2332,12 @@ ghb_find_audio_track(
        if (count > 10) count = 10;
        // Try to find an item that matches the preferred language and
        // the passthru codec type
+       max_chan = 0;
        passthru = (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)) != 0;
        if (passthru)
        {
                for (ii = 0; ii < count; ii++)
                {
-                       gint channels;
-
                        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
                                                                                                        title->list_audio, ii );
                        passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
@@ -2153,6 +2376,7 @@ ghb_find_audio_track(
                return track;
        }
        // Try to find an item that matches the preferred language
+       max_chan = 0;
        used = get_track_used(try_acodec, track_indices, count);
        for (ii = 0; ii < count; ii++)
        {
@@ -2169,13 +2393,18 @@ ghb_find_audio_track(
                        if (passthru_used[ii])
                                continue;
                }
+               channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+                                                                                               audio->in.channel_layout);
                // Find a track that is not visually impaired or dirctor's commentary
                if ((audio->lang.type < 2) &&
                        ((strcmp(lang, audio->lang.iso639_2) == 0) ||
                        (strcmp(lang, "und") == 0)))
                {
-                       track = ii;
-                       break;
+                       if (channels > max_chan)
+                       {
+                               track = ii;
+                               max_chan = channels;
+                       }
                }
        }
        if (track > -1)
@@ -2185,12 +2414,11 @@ ghb_find_audio_track(
        }
        // Try to fine an item that does not match the preferred language and
        // matches the passthru codec type
+       max_chan = 0;
        if (passthru)
        {
                for (ii = 0; ii < count; ii++)
                {
-                       gint channels;
-
                        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
                                                                                                        title->list_audio, ii );
                        passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
@@ -2227,6 +2455,7 @@ ghb_find_audio_track(
                return track;
        }
        // Try to fine an item that does not match the preferred language
+       max_chan = 0;
        used = get_track_used(try_acodec, track_indices, count);
        for (ii = 0; ii < count; ii++)
        {
@@ -2236,6 +2465,8 @@ ghb_find_audio_track(
                audio = (hb_audio_config_t*)hb_list_audio_config_item( 
                                                                                                        title->list_audio, ii );
                passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+               channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+                                                                                               audio->in.channel_layout);
                if (passthru_acodec && passthru)
                {
                        passthru_used = get_track_used(passthru_acodec, track_indices, count);
@@ -2246,8 +2477,11 @@ ghb_find_audio_track(
                // Find a track that is not visually impaired or dirctor's commentary
                if (audio->lang.type < 2)
                {
-                       track = ii;
-                       break;
+                       if (channels > max_chan)
+                       {
+                               track = ii;
+                               max_chan = channels;
+                       }
                }
        }
        if (track > -1)
@@ -2375,7 +2609,7 @@ ghb_find_subtitle_track(
                                continue;
 
                        subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
-                       if (((burn || force) && (subtitle->source == VOBSUB)) &&
+                       if ((!(burn || force) || (subtitle->source == VOBSUB)) &&
                                ((strcmp(lang, subtitle->iso639_2) == 0) ||
                                 (strcmp(lang, "und") == 0)))
                        {
@@ -2419,7 +2653,7 @@ small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
        gint ii;
        gchar *str;
        
-       g_debug("generic_opts_set ()\n");
+       g_debug("small_opts_set ()\n");
        if (name == NULL || opts == NULL) return;
        store = get_combo_box_store(builder, name);
        gtk_list_store_clear(store);
@@ -2540,7 +2774,7 @@ ghb_lookup_combo_string(const gchar *name, const GValue *gval)
        else if (strcmp(name, "VideoFramerate") == 0)
                return lookup_video_rate_option(gval);
        else if (strcmp(name, "AudioMixdown") == 0)
-               return lookup_mix_option(gval);
+               return lookup_mix_string(gval);
        else if (strcmp(name, "SrtLanguage") == 0)
                return lookup_audio_lang_option(gval);
        else if (strcmp(name, "PreferredLanguage") == 0)
@@ -2611,12 +2845,14 @@ ghb_update_ui_combo_box(
                generic_opts_set(ud->builder, "PictureDenoise", &denoise_opts);
                generic_opts_set(ud->builder, "VideoEncoder", &vcodec_opts);
                small_opts_set(ud->builder, "AudioEncoder", &acodec_opts);
-               generic_opts_set(ud->builder, "x264_direct", &direct_opts);
-               generic_opts_set(ud->builder, "x264_b_adapt", &badapt_opts);
-               generic_opts_set(ud->builder, "x264_me", &me_opts);
-               generic_opts_set(ud->builder, "x264_subme", &subme_opts);
-               generic_opts_set(ud->builder, "x264_analyse", &analyse_opts);
-               generic_opts_set(ud->builder, "x264_trellis", &trellis_opts);
+               small_opts_set(ud->builder, "x264_direct", &direct_opts);
+               small_opts_set(ud->builder, "x264_b_adapt", &badapt_opts);
+               small_opts_set(ud->builder, "x264_bpyramid", &bpyramid_opts);
+               small_opts_set(ud->builder, "x264_weighted_pframes", &weightp_opts);
+               small_opts_set(ud->builder, "x264_me", &me_opts);
+               small_opts_set(ud->builder, "x264_subme", &subme_opts);
+               small_opts_set(ud->builder, "x264_analyse", &analyse_opts);
+               small_opts_set(ud->builder, "x264_trellis", &trellis_opts);
        }
        else
        {
@@ -3853,7 +4089,6 @@ ghb_validate_subtitles(signal_user_data_t *ud)
        titleindex = ghb_settings_combo_int(ud->settings, "title");
     title = hb_list_item( list, titleindex );
        if (title == NULL) return FALSE;
-       gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
 
        const GValue *slist, *settings;
        gint count, ii, source;
@@ -3886,23 +4121,6 @@ ghb_validate_subtitles(signal_user_data_t *ud)
                {
                        one_burned = TRUE;
                }
-               if (!burned && mux == HB_MUX_MP4 && source == VOBSUB)
-               {
-                       // MP4 can only handle burned vobsubs.  make sure there isn't
-                       // already something burned in the list
-                       message = g_strdup_printf(
-                       "Your chosen container does not support soft bitmap subtitles.\n\n"
-                               "You should change your subtitle selections.\n"
-                               "If you continue, some subtitles will be lost.");
-                       if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, 
-                               "Cancel", "Continue"))
-                       {
-                               g_free(message);
-                               return FALSE;
-                       }
-                       g_free(message);
-                       break;
-               }
                if (source == SRTSUB)
                {
                        gchar *filename;
@@ -4090,7 +4308,7 @@ ghb_validate_audio(signal_user_data_t *ud)
                gboolean allow_dolby = TRUE;
                gboolean allow_dpl2 = TRUE;
                gboolean allow_6ch = TRUE;
-               allow_mono = (codec & ~HB_ACODEC_LAME);
+               allow_mono = TRUE;
                gint layout = taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
                allow_stereo =
                        ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
@@ -4460,7 +4678,11 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
        {
                job->vrate = 27000000;
                job->vrate_base = vrate;
-               job->cfr = 1;
+               gboolean pfr = ghb_settings_get_boolean(js, "VideoFrameratePFR");
+               if (pfr)
+                       job->cfr = 2;
+               else
+                       job->cfr = 1;
        }
 
        const GValue *audio_list;
@@ -4614,15 +4836,10 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
                subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
                if (subtitle == -1)
                {
-                       if (!burned && job->mux == HB_MUX_MKV)
+                       if (!burned)
                        {
                                job->select_subtitle_config.dest = PASSTHRUSUB;
                        }
-                       else if (!burned && job->mux == HB_MUX_MP4)
-                       {
-                               // Skip any non-burned vobsubs when output is mp4
-                               continue;
-                       }
                        else if (burned)
                        {
                                // Only allow one subtitle to be burned into the video
@@ -4645,17 +4862,10 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
                        if (subt != NULL)
                        {
                                sub_config = subt->config;
-                               if (!burned && job->mux == HB_MUX_MKV && 
-                                       subt->format == PICTURESUB)
+                               if (!burned && subt->format == PICTURESUB)
                                {
                                        sub_config.dest = PASSTHRUSUB;
                                }
-                               else if (!burned && job->mux == HB_MUX_MP4 && 
-                                       subt->format == PICTURESUB)
-                               {
-                                       // Skip any non-burned vobsubs when output is mp4
-                                       continue;
-                               }
                                else if ( burned && subt->format == PICTURESUB )
                                {
                                        // Only allow one subtitle to be burned into the video