OSDN Git Service

LinGui: add point-to-point
[handbrake-jp/handbrake-jp-git.git] / gtk / src / hb-backend.c
index 5d43d46..b577a5b 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;
@@ -1732,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, 
@@ -2007,37 +2065,51 @@ 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;
+       gint try_acodec;
        
        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))
@@ -2046,17 +2118,22 @@ ghb_find_audio_track(
                {
                        gint channels;
 
+                       audio = (hb_audio_config_t*)hb_list_audio_config_item( 
+                                                                                                       title->list_audio, ii );
+                       try_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+                       // Is the source track use a passthru capable codec?
+                       if (try_acodec == 0)
+                               continue;
+                       used = get_track_used(try_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)))
                        {
@@ -2067,6 +2144,11 @@ ghb_find_audio_track(
                                }
                        }
                }
+               try_acodec = fallback_acodec;
+       }
+       else
+       {
+               try_acodec = acodec;
        }
        if (track > -1)
        {
@@ -2074,11 +2156,13 @@ 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( 
+               audio = (hb_audio_config_t*)hb_list_audio_config_item( 
                                                                                                        title->list_audio, ii );
                // Find a track that is not visually impaired or dirctor's commentary
                if ((audio->lang.type < 2) &&
@@ -2102,17 +2186,22 @@ ghb_find_audio_track(
                {
                        gint channels;
 
+                       audio = (hb_audio_config_t*)hb_list_audio_config_item( 
+                                                                                                       title->list_audio, ii );
+                       try_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+                       // Is the source track use a passthru capable codec?
+                       if (try_acodec == 0)
+                               continue;
+                       used = get_track_used(try_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)
                                {
@@ -2121,6 +2210,11 @@ ghb_find_audio_track(
                                }
                        }
                }
+               try_acodec = fallback_acodec;
+       }
+       else
+       {
+               try_acodec = acodec;
        }
        if (track > -1)
        {
@@ -2128,11 +2222,13 @@ 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 );
                // Find a track that is not visually impaired or dirctor's commentary
                if (audio->lang.type < 2)
@@ -2149,8 +2245,9 @@ ghb_find_audio_track(
        // Last ditch, anything goes
        for (ii = 0; ii < count; ii++)
        {
-        audio = (hb_audio_config_t*)hb_list_audio_config_item( 
+               audio = (hb_audio_config_t*)hb_list_audio_config_item( 
                                                                                                        title->list_audio, ii );
+               // Has the track already been used with this codec?
                if (!used[ii])
                {
                        track = ii;
@@ -2479,6 +2576,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);
@@ -2551,7 +2649,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
@@ -2573,6 +2671,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;
@@ -2677,7 +2813,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;
@@ -2685,6 +2825,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);
@@ -2698,7 +2839,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);
@@ -2748,9 +2889,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;
@@ -2779,6 +2923,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)
 {
@@ -2943,6 +3092,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;
@@ -3011,8 +3176,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));
@@ -3033,6 +3199,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;
 }
 
@@ -3136,6 +3305,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 ) )
@@ -3151,7 +3321,6 @@ 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;
 
@@ -3857,7 +4026,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;
@@ -3894,7 +4063,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");
@@ -4073,13 +4242,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;
@@ -4089,14 +4287,14 @@ 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 = start; chap <= end; chap++)
                        {
                                hb_chapter_t * chapter_s;
                                gchar *name;
-                               
+
                                name = NULL;
                                if (chap-1 < count)
                                {