OSDN Git Service

LinGui: When translating legacy presets, vquality 0 means RF 0, not 0%
[handbrake-jp/handbrake-jp-git.git] / gtk / src / hb-backend.c
index caa11e9..fb76aa7 100644 (file)
@@ -70,6 +70,18 @@ index_str_init(gint max_index)
        }
 }
 
+static options_map_t d_point_to_point_opts[] =
+{
+       {"Chapters:",       "chapter", 0, "0"},
+       {"Seconds:", "time",    1, "1"},
+       {"Frames:",   "frame",   2, "2"},
+};
+combo_opts_t point_to_point_opts =
+{
+       sizeof(d_point_to_point_opts)/sizeof(options_map_t),
+       d_point_to_point_opts
+};
+
 static options_map_t d_when_complete_opts[] =
 {
        {"Do Nothing",            "nothing",  0, "0"},
@@ -359,6 +371,7 @@ typedef struct
 
 combo_name_map_t combo_name_map[] =
 {
+       {"PtoPType", &point_to_point_opts},
        {"WhenComplete", &when_complete_opts},
        {"PicturePAR", &par_opts},
        {"PictureModulus", &alignment_opts},
@@ -926,6 +939,33 @@ lookup_audio_rate_option(const GValue *rate)
        return result;
 }
 
+gint
+ghb_find_closest_audio_bitrate(gint codec, gint rate)
+{
+       gint ii;
+       gint low = 32;
+       gint high = 768;
+       gint result;
+
+       if (codec == HB_ACODEC_FAAC)
+               high = 160;
+
+       result = high;
+       for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+       {
+               if (hb_audio_bitrates[ii].rate < low)
+                       continue;
+               if (hb_audio_bitrates[ii].rate > high)
+                       break;
+               if (rate <= hb_audio_bitrates[ii].rate)
+               {
+                       result = hb_audio_bitrates[ii].rate;
+                       break;
+               }
+       }
+       return result;
+}
+
 static gint
 lookup_audio_bitrate_int(const GValue *rate)
 {
@@ -1017,8 +1057,8 @@ lookup_audio_lang_option(const GValue *rate)
        return result;
 }
 
-static GValue*
-get_acodec_value(gint val)
+GValue*
+ghb_lookup_acodec_value(gint val)
 {
        GValue *value = NULL;
        gint ii;
@@ -1354,11 +1394,12 @@ 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_6ch = acodec & ~HB_ACODEC_LAME;
        if (audio)
        {
-               allow_mono =
-                       (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
-                       (acodec & ~HB_ACODEC_LAME);
+               allow_mono = allow_mono &&
+                       (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA));
                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);
@@ -1367,9 +1408,8 @@ ghb_grey_combo_options(GtkBuilder *builder)
                        (layout == HB_INPUT_CH_LAYOUT_3F2R) || 
                        (layout == HB_INPUT_CH_LAYOUT_DOLBY);
                allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
-               allow_6ch =
+               allow_6ch = allow_6ch &&
                        (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
-                       (acodec & ~HB_ACODEC_LAME) &&
                        (layout == HB_INPUT_CH_LAYOUT_3F2R) && 
                        (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
        }
@@ -1381,10 +1421,14 @@ ghb_grey_combo_options(GtkBuilder *builder)
 }
 
 gint
-ghb_get_best_audio_bitrate(gint acodec, gint br)
+ghb_get_best_audio_bitrate(gint acodec, gint br, gint channels)
 {
-       if ((acodec & HB_ACODEC_FAAC) && br > 160)
-               br = 160;
+       if (acodec & HB_ACODEC_FAAC)
+       {
+       int maxbr = channels * 80;
+               if (br > maxbr)
+                       br = maxbr;
+       }
        return br;
 }
 
@@ -1490,7 +1534,7 @@ init_combo_box(GtkBuilder *builder, const gchar *name)
        cell = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE);
        gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell,
-               "text", 0, "sensitive", 1, NULL);
+               "markup", 0, "sensitive", 1, NULL);
        }
        else
        { // Combo box entry
@@ -1504,6 +1548,7 @@ audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rat
        GtkTreeIter iter;
        GtkListStore *store;
        gint ii;
+       gchar *str;
        
        g_debug("audio_samplerate_opts_set ()\n");
        store = get_combo_box_store(builder, name);
@@ -1511,7 +1556,7 @@ audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rat
        // Add an item for "Same As Source"
        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter, 
-                                          0, "Same as source", 
+                                          0, "<small>Same as source</small>", 
                                           1, TRUE, 
                                           2, "source", 
                                           3, 0.0, 
@@ -1520,13 +1565,15 @@ audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rat
        for (ii = 0; ii < count; ii++)
        {
                gtk_list_store_append(store, &iter);
+               str = g_strdup_printf("<small>%s</small>", rates[ii].string);
                gtk_list_store_set(store, &iter, 
-                                                  0, rates[ii].string, 
+                                                  0, str,
                                                   1, TRUE, 
                                                   2, rates[ii].string, 
                                                   3, (gdouble)rates[ii].rate, 
                                                   4, rates[ii].string, 
                                                   -1);
+               g_free(str);
        }
 }
 
@@ -1584,13 +1631,14 @@ mix_opts_set(GtkBuilder *builder, const gchar *name)
        GtkTreeIter iter;
        GtkListStore *store;
        gint ii;
+       gchar *str;
        
        g_debug("mix_opts_set ()\n");
        store = get_combo_box_store(builder, name);
        gtk_list_store_clear(store);
        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter, 
-                                          0, "None", 
+                                          0, "<small>None</small>", 
                                           1, TRUE, 
                                           2, "none", 
                                           3, 0.0, 
@@ -1599,13 +1647,16 @@ mix_opts_set(GtkBuilder *builder, const gchar *name)
        for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
        {
                gtk_list_store_append(store, &iter);
+               str = g_strdup_printf("<small>%s</small>",
+                       hb_audio_mixdowns[ii].human_readable_name);
                gtk_list_store_set(store, &iter, 
-                                                  0, hb_audio_mixdowns[ii].human_readable_name, 
+                                                  0, str,
                                                   1, TRUE, 
                                                   2, hb_audio_mixdowns[ii].short_name, 
                                                   3, (gdouble)hb_audio_mixdowns[ii].amixdown, 
                                                   4, hb_audio_mixdowns[ii].internal_name, 
                                                   -1);
+               g_free(str);
        }
 }
 
@@ -1721,14 +1772,32 @@ title_opts_set(GtkBuilder *builder, const gchar *name)
        for (ii = 0; ii < count; ii++)
        {
                title = (hb_title_t*)hb_list_item(list, ii);
-               if (title->duration != 0)
+               if (title->type == HB_STREAM_TYPE)
                {
-                       titles[ii]  = g_strdup_printf ("%d - %02dh%02dm%02ds",
-                               title->index, title->hours, title->minutes, title->seconds);
+                       if (title->duration != 0)
+                       {
+                               titles[ii]  = g_strdup_printf ("%d - %02dh%02dm%02ds - %s",
+                                       title->index, title->hours, title->minutes, title->seconds, 
+                                       title->name);
+                       }
+                       else
+                       {
+                               titles[ii]  = g_strdup_printf ("%d - %s", 
+                                                                               title->index, title->name);
+                       }
                }
                else
                {
-                       titles[ii]  = g_strdup_printf ("%d - Unknown Length", title->index);
+                       if (title->duration != 0)
+                       {
+                               titles[ii]  = g_strdup_printf ("%d - %02dh%02dm%02ds",
+                                       title->index, title->hours, title->minutes, title->seconds);
+                       }
+                       else
+                       {
+                               titles[ii]  = g_strdup_printf ("%d - Unknown Length", 
+                                                                               title->index);
+                       }
                }
                gtk_list_store_append(store, &iter);
                gtk_list_store_set(store, &iter, 
@@ -1777,6 +1846,7 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
     hb_audio_config_t * audio;
        gint ii;
        gint count = 0;
+       gchar *str;
        
        g_debug("audio_track_opts_set ()\n");
        store = get_combo_box_store(builder, name);
@@ -1807,7 +1877,7 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
                // No audio. set some default
                gtk_list_store_append(store, &iter);
                gtk_list_store_set(store, &iter, 
-                                                  0, "No Audio", 
+                                                  0, "<small>No Audio</small>", 
                                                   1, TRUE, 
                                                   2, "none", 
                                                   3, -1.0, 
@@ -1824,13 +1894,15 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
        {
         audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, ii );
                gtk_list_store_append(store, &iter);
+               str = g_strdup_printf("<small>%s</small>", audio->lang.description);
                gtk_list_store_set(store, &iter, 
-                                                  0, audio->lang.description, 
+                                                  0, str,
                                                   1, TRUE, 
                                                   2, index_str[ii], 
                                                   3, (gdouble)ii, 
                                                   4, index_str[ii], 
                                                   -1);
+               g_free(str);
                audio_track_opts.map[ii].option = audio->lang.description,
                audio_track_opts.map[ii].shortOpt = index_str[ii];
                audio_track_opts.map[ii].ivalue = ii;
@@ -1993,56 +2065,79 @@ ghb_get_source_audio_lang(gint titleindex, gint track)
        return lang;
 }
 
+static gboolean*
+get_track_used(gint acodec, GHashTable *track_indices, gint count)
+{
+       gboolean *used;
+
+       used = g_hash_table_lookup(track_indices, &acodec);
+       if (used == NULL)
+       {
+               gint *key;
+
+               used = g_malloc0(count * sizeof(gboolean));
+               key = g_malloc(sizeof(gint));
+               *key = acodec;
+               g_hash_table_insert(track_indices, key, used);
+       }
+       return used;
+}
+
 gint
 ghb_find_audio_track(
        gint titleindex, 
        const gchar *lang, 
        gint acodec,
+       gint fallback_acodec,
        GHashTable *track_indices)
 {
        hb_list_t  * list;
        hb_title_t * title;
-    hb_audio_config_t * audio;
+       hb_audio_config_t * audio;
        gint ii;
        gint count = 0;
        gint track = -1;
        gint max_chan = 0;
        gboolean *used;
+       gboolean *passthru_used;
+       gint try_acodec;
+       gint passthru_acodec;
+       gboolean passthru;
        
        g_debug("find_audio_track ()\n");
        if (h_scan == NULL) return -1;
        list = hb_get_titles( h_scan );
-    title = (hb_title_t*)hb_list_item( list, titleindex );
+       title = (hb_title_t*)hb_list_item( list, titleindex );
        if (title != NULL)
        {
                count = hb_list_count( title->list_audio );
        }
        if (count > 10) count = 10;
-       used = g_hash_table_lookup(track_indices, &acodec);
-       if (used == NULL)
-       {
-               used = g_malloc0(count * sizeof(gboolean));
-               g_hash_table_insert(track_indices, &acodec, used);
-       }
        // Try to find an item that matches the preferred language and
        // the passthru codec type
-       if (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
+       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;
+                       // Is the source track use a passthru capable codec?
+                       if (passthru_acodec == 0)
+                               continue;
+                       used = get_track_used(passthru_acodec, track_indices, count);
+                       // Has the track already been used with this codec?
                        if (used[ii])
                                continue;
 
-               audio = (hb_audio_config_t*)hb_list_audio_config_item( 
-                                                                                                       title->list_audio, ii );
                        channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
                                                                                                        audio->in.channel_layout);
                        // Find a track that is not visually impaired or dirctor's
                        // commentary, and has the highest channel count.
-                       if ((audio->in.codec & acodec) &&
-                               (audio->lang.type < 2) &&
+                       if ((audio->lang.type < 2) &&
                                ((strcmp(lang, audio->lang.iso639_2) == 0) ||
                                (strcmp(lang, "und") == 0)))
                        {
@@ -2053,6 +2148,11 @@ ghb_find_audio_track(
                                }
                        }
                }
+               try_acodec = fallback_acodec;
+       }
+       else
+       {
+               try_acodec = acodec;
        }
        if (track > -1)
        {
@@ -2060,12 +2160,22 @@ ghb_find_audio_track(
                return track;
        }
        // Try to find an item that matches the preferred language
+       used = get_track_used(try_acodec, track_indices, count);
        for (ii = 0; ii < count; ii++)
        {
+               // Has the track already been used with this codec?
                if (used[ii])
                        continue;
-        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
-                                                                                                       title->list_audio, ii );
+               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;
+               if (passthru_acodec && passthru)
+               {
+                       passthru_used = get_track_used(passthru_acodec, track_indices, count);
+                       // Has the track already been used with this codec for passthru?
+                       if (passthru_used[ii])
+                               continue;
+               }
                // Find a track that is not visually impaired or dirctor's commentary
                if ((audio->lang.type < 2) &&
                        ((strcmp(lang, audio->lang.iso639_2) == 0) ||
@@ -2082,23 +2192,28 @@ ghb_find_audio_track(
        }
        // Try to fine an item that does not match the preferred language and
        // matches the passthru codec type
-       if (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
+       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;
+                       // Is the source track use a passthru capable codec?
+                       if (passthru_acodec == 0)
+                               continue;
+                       used = get_track_used(passthru_acodec, track_indices, count);
+                       // Has the track already been used with this codec?
                        if (used[ii])
                                continue;
 
-               audio = (hb_audio_config_t*)hb_list_audio_config_item( 
-                                                                                                       title->list_audio, ii );
                        channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
                                                                                                        audio->in.channel_layout);
                        // Find a track that is not visually impaired or dirctor's
                        // commentary, and has the highest channel count.
-                       if ((audio->in.codec & acodec) &&
-                               (audio->lang.type < 2))
+                       if (audio->lang.type < 2)
                        {
                                if (channels > max_chan)
                                {
@@ -2107,6 +2222,11 @@ ghb_find_audio_track(
                                }
                        }
                }
+               try_acodec = fallback_acodec;
+       }
+       else
+       {
+               try_acodec = acodec;
        }
        if (track > -1)
        {
@@ -2114,12 +2234,22 @@ ghb_find_audio_track(
                return track;
        }
        // Try to fine an item that does not match the preferred language
+       used = get_track_used(try_acodec, track_indices, count);
        for (ii = 0; ii < count; ii++)
        {
+               // Has the track already been used with this codec?
                if (used[ii])
                        continue;
-        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
+               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;
+               if (passthru_acodec && passthru)
+               {
+                       passthru_used = get_track_used(passthru_acodec, track_indices, count);
+                       // Has the track already been used with this codec for passthru?
+                       if (passthru_used[ii])
+                               continue;
+               }
                // Find a track that is not visually impaired or dirctor's commentary
                if (audio->lang.type < 2)
                {
@@ -2135,8 +2265,17 @@ ghb_find_audio_track(
        // Last ditch, anything goes
        for (ii = 0; ii < count; ii++)
        {
-        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
-                                                                                                       title->list_audio, ii );
+               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;
+               if (passthru_acodec && passthru)
+               {
+                       passthru_used = get_track_used(passthru_acodec, track_indices, count);
+                       // Has the track already been used with this codec for passthru?
+                       if (passthru_used[ii])
+                               continue;
+               }
+               // Has the track already been used with this codec?
                if (!used[ii])
                {
                        track = ii;
@@ -2279,6 +2418,33 @@ generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
        }
 }
 
+static void
+small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
+{
+       GtkTreeIter iter;
+       GtkListStore *store;
+       gint ii;
+       gchar *str;
+       
+       g_debug("generic_opts_set ()\n");
+       if (name == NULL || opts == NULL) return;
+       store = get_combo_box_store(builder, name);
+       gtk_list_store_clear(store);
+       for (ii = 0; ii < opts->count; ii++)
+       {
+               gtk_list_store_append(store, &iter);
+               str = g_strdup_printf("<small>%s</small>", opts->map[ii].option);
+               gtk_list_store_set(store, &iter, 
+                                                  0, str,
+                                                  1, TRUE, 
+                                                  2, opts->map[ii].shortOpt, 
+                                                  3, opts->map[ii].ivalue, 
+                                                  4, opts->map[ii].svalue, 
+                                                  -1);
+               g_free(str);
+       }
+}
+
 combo_opts_t*
 find_combo_table(const gchar *name)
 {
@@ -2438,6 +2604,7 @@ ghb_update_ui_combo_box(
                audio_track_opts_set(ud->builder, "AudioTrack", user_data);
                subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
                generic_opts_set(ud->builder, "VideoQualityGranularity", &vqual_granularity_opts);
+               generic_opts_set(ud->builder, "PtoPType", &point_to_point_opts);
                generic_opts_set(ud->builder, "WhenComplete", &when_complete_opts);
                generic_opts_set(ud->builder, "PicturePAR", &par_opts);
                generic_opts_set(ud->builder, "PictureModulus", &alignment_opts);
@@ -2450,7 +2617,7 @@ ghb_update_ui_combo_box(
                generic_opts_set(ud->builder, "PictureDecomb", &decomb_opts);
                generic_opts_set(ud->builder, "PictureDenoise", &denoise_opts);
                generic_opts_set(ud->builder, "VideoEncoder", &vcodec_opts);
-               generic_opts_set(ud->builder, "AudioEncoder", &acodec_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);
@@ -2510,7 +2677,7 @@ init_ui_combo_boxes(GtkBuilder *builder)
 }
        
 static const char * turbo_opts = 
-       "ref=1:subme=1:me=dia:analyse=none:trellis=0:"
+       "ref=1:subme=2:me=dia:analyse=none:trellis=0:"
        "no-fast-pskip=0:8x8dct=0";
 
 // Construct the x264 options string
@@ -2532,6 +2699,44 @@ ghb_build_x264opts_string(GValue *settings)
 }
 
 void
+ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
+{
+       hb_list_t  * list;
+       hb_title_t * title;
+    hb_chapter_t * chapter;
+       gint count, c;
+       gint64 duration;
+       
+       *hh = *mm = *ss = 0;
+       if (h_scan == NULL) return;
+       list = hb_get_titles( h_scan );
+    title = (hb_title_t*)hb_list_item( list, tt );
+       if (title == NULL) return;
+
+       *hh = title->hours;
+       *mm = title->minutes;
+       *ss = title->seconds;
+
+       count = hb_list_count(title->list_chapter);
+       if (sc > count) sc = count;
+       if (ec > count) ec = count;
+
+       if (sc == 1 && ec == count)
+               return;
+
+       duration = 0;
+       for (c = sc; c <= ec; c++)
+       {
+               chapter = hb_list_item(title->list_chapter, c-1);
+               duration += chapter->duration;
+       }
+
+       *hh =   duration / 90000 / 3600;
+       *mm = ((duration / 90000) % 3600) / 60;
+       *ss =  (duration / 90000) % 60;
+}
+
+void
 ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss)
 {
        hb_list_t  * list;
@@ -2615,14 +2820,14 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
        GtkListStore *store;
        gchar *str;
        
-       g_debug("audio_rate_opts_add ()\n");
+       g_debug("audio_bitrate_opts_add ()\n");
 
        if (rate < 8) return;
 
        store = get_combo_box_store(builder, name);
        if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
        {
-               str = g_strdup_printf ("%d", rate);
+               str = g_strdup_printf ("<small>%d</small>", rate);
                gtk_list_store_append(store, &iter);
                gtk_list_store_set(store, &iter, 
                                                   0, str, 
@@ -2636,7 +2841,11 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
 }
 
 static void
-audio_bitrate_opts_clean(GtkBuilder *builder, const gchar *name, gint last_rate)
+audio_bitrate_opts_clean(
+       GtkBuilder *builder, 
+       const gchar *name, 
+       gint first_rate, 
+       gint last_rate)
 {
        GtkTreeIter iter;
        GtkListStore *store;
@@ -2644,6 +2853,7 @@ audio_bitrate_opts_clean(GtkBuilder *builder, const gchar *name, gint last_rate)
        gboolean done = FALSE;
        gint ii = 0;
        guint last = (guint)last_rate;
+       guint first = (guint)first_rate;
        
        g_debug("audio_bitrate_opts_clean ()\n");
        store = get_combo_box_store(builder, name);
@@ -2657,7 +2867,7 @@ audio_bitrate_opts_clean(GtkBuilder *builder, const gchar *name, gint last_rate)
                        {
                                done = !gtk_list_store_remove(store, &iter);
                        }
-                       else if (ivalue > last)
+                       else if (ivalue < first || ivalue > last)
                        {
                                ii++;
                                gtk_list_store_set(store, &iter, 1, FALSE, -1);
@@ -2679,6 +2889,7 @@ audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
        GtkTreeIter iter;
        GtkListStore *store;
        gint ii;
+       gchar *str;
        
        g_debug("audio_bitrate_opts_set ()\n");
        store = get_combo_box_store(builder, name);
@@ -2686,13 +2897,16 @@ audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
        for (ii = 0; ii < hb_audio_bitrates_count; ii++)
        {
                gtk_list_store_append(store, &iter);
+               str = g_strdup_printf ("<small>%s</small>", 
+                       hb_audio_bitrates[ii].string);
                gtk_list_store_set(store, &iter, 
-                                                  0, hb_audio_bitrates[ii].string, 
+                                                  0, str,
                                                   1, TRUE, 
                                                   2, hb_audio_bitrates[ii].string, 
                                                   3, (gdouble)hb_audio_bitrates[ii].rate, 
                                                   4, hb_audio_bitrates[ii].string, 
                                                   -1);
+               g_free(str);
        }
 }
 
@@ -2703,9 +2917,12 @@ ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate)
 }
 
 void
-ghb_set_default_bitrate_opts(GtkBuilder *builder, gint last_rate)
+ghb_set_default_bitrate_opts(
+       GtkBuilder *builder, 
+       gint first_rate, 
+       gint last_rate)
 {
-       audio_bitrate_opts_clean(builder, "AudioBitrate", last_rate);
+       audio_bitrate_opts_clean(builder, "AudioBitrate", first_rate, last_rate);
 }
 
 static ghb_status_t hb_status;
@@ -2734,6 +2951,11 @@ ghb_backend_close()
        hb_close(&h_scan);
 }
 
+void ghb_backend_scan_stop()
+{
+    hb_scan_stop( h_scan );
+}
+
 void
 ghb_backend_scan(const gchar *path, gint titleindex, gint preview_count)
 {
@@ -2898,6 +3120,22 @@ ghb_track_status()
         case HB_STATE_WORKING:
                        hb_status.queue.state |= GHB_STATE_WORKING;
                        hb_status.queue.state &= ~GHB_STATE_PAUSED;
+                       hb_status.queue.state &= ~GHB_STATE_SEARCHING;
+                       hb_status.queue.job_cur = p.job_cur;
+                       hb_status.queue.job_count = p.job_count;
+                       hb_status.queue.progress = p.progress;
+                       hb_status.queue.rate_cur = p.rate_cur;
+                       hb_status.queue.rate_avg = p.rate_avg;
+                       hb_status.queue.hours = p.hours;
+                       hb_status.queue.minutes = p.minutes;
+                       hb_status.queue.seconds = p.seconds;
+                       hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
+            break;
+
+        case HB_STATE_SEARCHING:
+                       hb_status.queue.state |= GHB_STATE_SEARCHING;
+                       hb_status.queue.state &= ~GHB_STATE_WORKING;
+                       hb_status.queue.state &= ~GHB_STATE_PAUSED;
                        hb_status.queue.job_cur = p.job_cur;
                        hb_status.queue.job_count = p.job_count;
                        hb_status.queue.progress = p.progress;
@@ -2928,6 +3166,7 @@ ghb_track_status()
                        hb_status.queue.state &= ~GHB_STATE_MUXING;
                        hb_status.queue.state &= ~GHB_STATE_PAUSED;
                        hb_status.queue.state &= ~GHB_STATE_WORKING;
+                       hb_status.queue.state &= ~GHB_STATE_SEARCHING;
                        switch (p.error)
                        {
                        case HB_ERROR_NONE:
@@ -2966,8 +3205,9 @@ ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
                return FALSE;
        }
 
-    title = hb_list_item( list, titleindex );
+       title = hb_list_item( list, titleindex );
        if (title == NULL) return FALSE;        // Bad titleindex
+       tinfo->index = titleindex;
        tinfo->width = title->width;
        tinfo->height = title->height;
        memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
@@ -2988,6 +3228,9 @@ ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
        tinfo->duration = title->duration;
 
        tinfo->angle_count = title->angle_count;
+       tinfo->path = title->path;
+       tinfo->name = title->name;
+       tinfo->type = title->type;
        return TRUE;
 }
 
@@ -3091,6 +3334,7 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
        static gboolean busy = FALSE;
        
        g_debug("ghb_set_scale ()\n");
+       picture_settings_deps(ud);
        if (h_scan == NULL) return;
        list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
@@ -3106,11 +3350,15 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
        job   = title->job;
        if (job == NULL) return;
 
-       picture_settings_deps(ud);
        if (busy) return;
        busy = TRUE;
 
-       
+       if (!ud->dont_clear_presets && (keep_width || keep_height))
+       {
+               ghb_settings_set_int(ud->settings, "PictureWidth", 0);
+               ghb_settings_set_int(ud->settings, "PictureHeight", 0);
+       }
+
        // First configure widgets
        mod = ghb_settings_combo_int(ud->settings, "PictureModulus");
        pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR");
@@ -3246,7 +3494,7 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
                job->anamorphic.dar_height = 0;
 
                if (keep_height && pic_par == 2)
-                       width = ((double)height * crop_width / crop_height) + 0.5;
+                       width = ((double)height * crop_width / crop_height) + mod / 2;
                job->width = width;
                job->height = height;
                job->maxWidth = max_width;
@@ -3497,7 +3745,7 @@ ghb_validate_filters(signal_user_data_t *ud)
        if (!decomb_deint && index == 1)
        {
                str = ghb_settings_get_string(ud->settings, "PictureDeinterlaceCustom");
-               if (!ghb_validate_filter_string(str, 4))
+               if (!ghb_validate_filter_string(str, -1))
                {
                        message = g_strdup_printf(
                                                "Invalid Deinterlace Settings:\n\n%s\n",
@@ -3514,7 +3762,7 @@ ghb_validate_filters(signal_user_data_t *ud)
        if (index == 1)
        {
                str = ghb_settings_get_string(ud->settings, "PictureDetelecineCustom");
-               if (!ghb_validate_filter_string(str, 6))
+               if (!ghb_validate_filter_string(str, -1))
                {
                        message = g_strdup_printf(
                                                "Invalid Detelecine Settings:\n\n%s\n",
@@ -3531,7 +3779,7 @@ ghb_validate_filters(signal_user_data_t *ud)
        if (decomb_deint && index == 1)
        {
                str = ghb_settings_get_string(ud->settings, "PictureDecombCustom");
-               if (!ghb_validate_filter_string(str, 15))
+               if (!ghb_validate_filter_string(str, -1))
                {
                        message = g_strdup_printf(
                                                "Invalid Decomb Settings:\n\n%s\n",
@@ -3548,7 +3796,7 @@ ghb_validate_filters(signal_user_data_t *ud)
        if (index == 1)
        {
                str = ghb_settings_get_string(ud->settings, "PictureDenoiseCustom");
-               if (!ghb_validate_filter_string(str, 4))
+               if (!ghb_validate_filter_string(str, -1))
                {
                        message = g_strdup_printf(
                                                "Invalid Denoise Settings:\n\n%s\n",
@@ -3807,7 +4055,7 @@ ghb_validate_audio(signal_user_data_t *ud)
                        {
                                codec = HB_ACODEC_FAAC;
                        }
-                       value = get_acodec_value(codec);
+                       value = ghb_lookup_acodec_value(codec);
                        ghb_settings_take_value(asettings, "AudioEncoder", value);
                }
                gchar *a_unsup = NULL;
@@ -3844,7 +4092,7 @@ ghb_validate_audio(signal_user_data_t *ud)
                                return FALSE;
                        }
                        g_free(message);
-                       value = get_acodec_value(codec);
+                       value = ghb_lookup_acodec_value(codec);
                        ghb_settings_take_value(asettings, "AudioEncoder", value);
                }
                gint mix = ghb_settings_combo_int (asettings, "AudioMixdown");
@@ -4023,13 +4271,42 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
        }
        if (!job->start_at_preview)
        {
-               gint chapter_start, chapter_end;
-               chapter_start = ghb_settings_get_int(js, "start_chapter");
-               chapter_end = ghb_settings_get_int(js, "end_chapter");
+               gint start, end;
                gint num_chapters = hb_list_count(title->list_chapter);
-               job->chapter_start = MIN( num_chapters, chapter_start );
-               job->chapter_end   = MAX( job->chapter_start, chapter_end );
+               gint duration = title->duration / 90000;
+               job->chapter_start = 1;
+               job->chapter_end = num_chapters;
 
+               if (ghb_settings_combo_int(js, "PtoPType") == 0)
+               {
+                       start = ghb_settings_get_int(js, "start_point");
+                       end = ghb_settings_get_int(js, "end_point");
+                       job->chapter_start = MIN( num_chapters, start );
+                       job->chapter_end   = MAX( job->chapter_start, end );
+
+               }
+               if (ghb_settings_combo_int(js, "PtoPType") == 1)
+               {
+                       job->chapter_start = 1;
+                       job->chapter_end = num_chapters;
+                       start = ghb_settings_get_int(js, "start_point");
+                       end = ghb_settings_get_int(js, "end_point");
+                       job->pts_to_start = (int64_t)MIN(duration-1, start) * 90000;
+                       job->pts_to_stop = (int64_t)MAX(start+1, end) * 90000 - 
+                                                               job->pts_to_start;
+               }
+               if (ghb_settings_combo_int(js, "PtoPType") == 2)
+               {
+                       job->chapter_start = 1;
+                       job->chapter_end = num_chapters;
+                       start = ghb_settings_get_int(js, "start_point");
+                       end = ghb_settings_get_int(js, "end_point");
+                       gint64 max_frames;
+                       max_frames = (gint64)duration * title->rate / title->rate_base;
+                       job->frame_to_start = (int64_t)MIN(max_frames-1, start-1);
+                       job->frame_to_stop = (int64_t)MAX(start, end-1) - 
+                                                                job->frame_to_start;
+               }
                job->chapter_markers = ghb_settings_get_boolean(js, "ChapterMarkers");
                if (job->chapter_start == job->chapter_end)
                        job->chapter_markers = 0;
@@ -4039,25 +4316,22 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
                        GValue *chapter;
                        gint chap;
                        gint count;
-               
+
                        chapters = ghb_settings_get_value(js, "chapter_list");
                        count = ghb_array_len(chapters);
-                       for(chap = chapter_start; chap <= chapter_end; chap++)
+                       for(chap = 0; chap < count; chap++)
                        {
                                hb_chapter_t * chapter_s;
                                gchar *name;
-                               
+
                                name = NULL;
-                               if (chap-1 < count)
-                               {
-                                       chapter = ghb_array_get_nth(chapters, chap-1);
-                                       name = ghb_value_string(chapter); 
-                               }
+                               chapter = ghb_array_get_nth(chapters, chap);
+                               name = ghb_value_string(chapter); 
                                if (name == NULL)
                                {
-                                       name = g_strdup_printf ("Chapter %2d", chap);
+                                       name = g_strdup_printf ("Chapter %2d", chap+1);
                                }
-                               chapter_s = hb_list_item( job->title->list_chapter, chap - 1);
+                               chapter_s = hb_list_item( job->title->list_chapter, chap);
                                strncpy(chapter_s->title, name, 1023);
                                chapter_s->title[1023] = '\0';
                                g_free(name);
@@ -4262,19 +4536,29 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
                }
                else
                {
+                       int channels;
+
                        audio.out.mixdown = ghb_settings_combo_int(asettings, "AudioMixdown");
+                       if (audio.out.mixdown == HB_AMIXDOWN_MONO)
+                               channels = 1;
+                       else if (audio.out.mixdown == HB_AMIXDOWN_6CH)
+                               channels = 6;
+                       else
+                               channels = 2;
+
                        // Make sure the mixdown is valid and pick a new one if not.
                        audio.out.mixdown = ghb_get_best_mix(titleindex, 
                                audio.in.track, audio.out.codec, audio.out.mixdown);
                        audio.out.bitrate = 
                                ghb_settings_combo_int(asettings, "AudioBitrate");
-                       audio.out.bitrate = ghb_get_best_audio_bitrate(
-                               audio.out.codec, audio.out.bitrate);
                        gint srate = ghb_settings_combo_int(asettings, "AudioSamplerate");
                        if (srate == 0) // 0 is same as source
                                audio.out.samplerate = taudio->in.samplerate;
                        else
                                audio.out.samplerate = srate;
+
+                       audio.out.bitrate = ghb_get_best_audio_bitrate(
+                               audio.out.codec, audio.out.bitrate, channels);
                }
 
                // Add it to the jobs audio list
@@ -4295,7 +4579,6 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
 
        dest_str = ghb_settings_get_string(js, "destination");
        job->file = dest_str;
-       job->crf = ghb_settings_get_boolean(js, "constant_rate_factor");
 
        const GValue *subtitle_list;
        gint subtitle;