#include "settings.h"
#include "callbacks.h"
#include "subtitlehandler.h"
+#include "audiohandler.h"
+#include "x264handler.h"
#include "preview.h"
#include "values.h"
#include "lang.h"
}
}
+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"},
+ {"Show Notification", "notify", 1, "1"},
+ {"Put Computer To Sleep", "sleep", 2, "2"},
+ {"Shutdown Computer", "shutdown", 3, "3"},
+};
+combo_opts_t when_complete_opts =
+{
+ sizeof(d_when_complete_opts)/sizeof(options_map_t),
+ d_when_complete_opts
+};
+
static options_map_t d_par_opts[] =
{
{"Off", "0", 0, "0"},
d_logging_opts
};
+static options_map_t d_log_longevity_opts[] =
+{
+ {"Week", "week", 7, "7"},
+ {"Month", "month", 30, "30"},
+ {"Year", "year", 365, "365"},
+ {"Immortal", "immortal", 366, "366"},
+};
+combo_opts_t log_longevity_opts =
+{
+ sizeof(d_log_longevity_opts)/sizeof(options_map_t),
+ d_log_longevity_opts
+};
+
+static options_map_t d_appcast_update_opts[] =
+{
+ {"Never", "never", 0, "never"},
+ {"Daily", "daily", 1, "daily"},
+ {"Weekly", "weekly", 2, "weekly"},
+ {"Monthly", "monthly", 3, "monthly"},
+};
+combo_opts_t appcast_update_opts =
+{
+ sizeof(d_appcast_update_opts)/sizeof(options_map_t),
+ d_appcast_update_opts
+};
+
static options_map_t d_vqual_granularity_opts[] =
{
{"0.2", "0.2", 0.2, "0.2"},
{
{"MKV", "mkv", HB_MUX_MKV, "mkv"},
{"MP4", "mp4", HB_MUX_MP4, "mp4"},
- {"M4V", "m4v", HB_MUX_MP4, "m4v"},
};
combo_opts_t container_opts =
{
static options_map_t d_detel_opts[] =
{
- {"None", "none", 0, ""},
+ {"Off", "off", 0, ""},
{"Custom", "custom", 1, ""},
{"Default","default",2, NULL},
};
static options_map_t d_decomb_opts[] =
{
- {"None", "none", 0, ""},
+ {"Off", "off", 0, ""},
{"Custom", "custom", 1, ""},
{"Default","default",2, NULL},
};
static options_map_t d_deint_opts[] =
{
- {"None", "none", 0, ""},
+ {"Off", "off", 0, ""},
{"Custom", "custom", 1, ""},
{"Fast", "fast", 2, "-1:-1:-1:0:1"},
{"Slow", "slow", 3, "2:-1:-1:0:1"},
static options_map_t d_denoise_opts[] =
{
- {"None", "none", 0, ""},
+ {"Off", "off", 0, ""},
{"Custom", "custom", 1, ""},
{"Weak", "weak", 2, "2:1:2:3"},
{"Medium", "medium", 3, "3:2:2:3"},
static options_map_t d_vcodec_opts[] =
{
{"H.264 (x264)", "x264", HB_VCODEC_X264, ""},
- {"MPEG-4 (FFMPEG)", "ffmpeg", HB_VCODEC_FFMPEG, ""},
- {"Theora", "theora", HB_VCODEC_THEORA, ""},
+ {"MPEG-4 (FFmpeg)", "ffmpeg", HB_VCODEC_FFMPEG, ""},
+ {"VP3 (Theora)", "theora", HB_VCODEC_THEORA, ""},
};
combo_opts_t vcodec_opts =
{
static options_map_t d_acodec_opts[] =
{
- {"AAC (faac)", "faac", HB_ACODEC_FAAC, "faac"},
- {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
+ {"AAC (faac)", "faac", HB_ACODEC_FAAC, "faac"},
+ {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
{"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"},
- {"AC3 (pass-thru)", "ac3", HB_ACODEC_AC3, "ac3"},
- {"DTS (pass-thru)", "dts", HB_ACODEC_DCA, "dts"},
- {"Auto Pass-Thru", "auto", HB_ACODEC_DCA|HB_ACODEC_AC3, "auto"},
+ {"AC3 (pass-thru)", "ac3", HB_ACODEC_AC3, "ac3"},
+ {"DTS (pass-thru)", "dts", HB_ACODEC_DCA, "dts"},
+ {"Choose For Me", "auto", HB_ACODEC_MASK, "auto"},
};
combo_opts_t acodec_opts =
{
{"7", "7", 7, "7"},
{"8", "8", 8, "8"},
{"9", "9", 9, "9"},
+ {"10", "10", 10, "10"},
};
combo_opts_t subme_opts =
{
combo_name_map_t combo_name_map[] =
{
+ {"PtoPType", &point_to_point_opts},
+ {"WhenComplete", &when_complete_opts},
{"PicturePAR", &par_opts},
{"PictureModulus", &alignment_opts},
{"LoggingLevel", &logging_opts},
+ {"LogLongevity", &log_longevity_opts},
+ {"check_updates", &appcast_update_opts},
{"VideoQualityGranularity", &vqual_granularity_opts},
{"FileFormat", &container_opts},
{"PictureDeinterlace", &deint_opts},
{NULL, NULL}
};
+const gchar *srt_codeset_table[] =
+{
+ "ANSI_X3.4-1968",
+ "ANSI_X3.4-1986",
+ "ANSI_X3.4",
+ "ANSI_X3.110-1983",
+ "ANSI_X3.110",
+ "ASCII",
+ "ECMA-114",
+ "ECMA-118",
+ "ECMA-128",
+ "ECMA-CYRILLIC",
+ "IEC_P27-1",
+ "ISO-8859-1",
+ "ISO-8859-2",
+ "ISO-8859-3",
+ "ISO-8859-4",
+ "ISO-8859-5",
+ "ISO-8859-6",
+ "ISO-8859-7",
+ "ISO-8859-8",
+ "ISO-8859-9",
+ "ISO-8859-9E",
+ "ISO-8859-10",
+ "ISO-8859-11",
+ "ISO-8859-13",
+ "ISO-8859-14",
+ "ISO-8859-15",
+ "ISO-8859-16",
+ "UTF-7",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16LE",
+ "UTF-16BE",
+ "UTF-32",
+ "UTF-32LE",
+ "UTF-32BE",
+ NULL
+};
+#define SRT_TABLE_SIZE (sizeof(srt_codeset_table)/ sizeof(char*)-1)
+
#if 0
typedef struct iso639_lang_t
{
{ "Cree", "", "cr", "cre" },
{ "Czech", "", "cs", "ces", "cze" },
{ "Danish", "Dansk", "da", "dan" },
+ { "German", "Deutsch", "de", "deu", "ger" },
{ "Divehi", "", "dv", "div" },
- { "Dutch", "Nederlands", "nl", "nld", "dut" },
{ "Dzongkha", "", "dz", "dzo" },
{ "English", "English", "en", "eng" },
+ { "Spanish", "Espanol", "es", "spa" },
{ "Esperanto", "", "eo", "epo" },
{ "Estonian", "", "et", "est" },
{ "Ewe", "", "ee", "ewe" },
{ "Faroese", "", "fo", "fao" },
{ "Fijian", "", "fj", "fij" },
- { "Finnish", "Suomi", "fi", "fin" },
{ "French", "Francais", "fr", "fra", "fre" },
{ "Western Frisian", "", "fy", "fry" },
{ "Fulah", "", "ff", "ful" },
{ "Georgian", "", "ka", "kat", "geo" },
- { "German", "Deutsch", "de", "deu", "ger" },
{ "Gaelic (Scots)", "", "gd", "gla" },
{ "Irish", "", "ga", "gle" },
{ "Galician", "", "gl", "glg" },
{ "Herero", "", "hz", "her" },
{ "Hindi", "", "hi", "hin" },
{ "Hiri Motu", "", "ho", "hmo" },
- { "Hungarian", "Magyar", "hu", "hun" },
+ { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
{ "Igbo", "", "ig", "ibo" },
- { "Icelandic", "Islenska", "is", "isl", "ice" },
{ "Ido", "", "io", "ido" },
+ { "Icelandic", "Islenska", "is", "isl", "ice" },
{ "Sichuan Yi", "", "ii", "iii" },
{ "Inuktitut", "", "iu", "iku" },
{ "Interlingue", "", "ie", "ile" },
{ "Luba-Katanga", "", "lu", "lub" },
{ "Ganda", "", "lg", "lug" },
{ "Macedonian", "", "mk", "mkd", "mac" },
+ { "Hungarian", "Magyar", "hu", "hun" },
{ "Marshallese", "", "mh", "mah" },
{ "Malayalam", "", "ml", "mal" },
{ "Maori", "", "mi", "mri", "mao" },
{ "Mongolian", "", "mn", "mon" },
{ "Nauru", "", "na", "nau" },
{ "Navajo", "", "nv", "nav" },
+ { "Dutch", "Nederlands", "nl", "nld", "dut" },
{ "Ndebele, South", "", "nr", "nbl" },
{ "Ndebele, North", "", "nd", "nde" },
{ "Ndonga", "", "ng", "ndo" },
{ "Nepali", "", "ne", "nep" },
+ { "Norwegian", "Norsk", "no", "nor" },
{ "Norwegian Nynorsk", "", "nn", "nno" },
{ "Norwegian Bokmål", "", "nb", "nob" },
- { "Norwegian", "Norsk", "no", "nor" },
{ "Chichewa; Nyanja", "", "ny", "nya" },
{ "Occitan", "", "oc", "oci" },
{ "Ojibwa", "", "oj", "oji" },
{ "Sango", "", "sg", "sag" },
{ "Sanskrit", "", "sa", "san" },
{ "Serbian", "", "sr", "srp", "scc" },
- { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
{ "Sinhala", "", "si", "sin" },
{ "Slovak", "", "sk", "slk", "slo" },
{ "Slovenian", "", "sl", "slv" },
{ "Sindhi", "", "sd", "snd" },
{ "Somali", "", "so", "som" },
{ "Sotho, Southern", "", "st", "sot" },
- { "Spanish", "Espanol", "es", "spa" },
{ "Sardinian", "", "sc", "srd" },
{ "Swati", "", "ss", "ssw" },
{ "Sundanese", "", "su", "sun" },
+ { "Finnish", "Suomi", "fi", "fin" },
{ "Swahili", "", "sw", "swa" },
{ "Swedish", "Svenska", "sv", "swe" },
{ "Tahitian", "", "ty", "tah" },
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)
{
{
if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
{
- result = ghb_language_table[ii].eng_name;
+ if (ghb_language_table[ii].native_name[0] != 0)
+ result = ghb_language_table[ii].native_name;
+ else
+ result = ghb_language_table[ii].eng_name;
break;
}
}
return result;
}
-static GValue*
-get_acodec_value(gint val)
+GValue*
+ghb_lookup_acodec_value(gint val)
{
GValue *value = NULL;
gint ii;
gint titleindex;
if (track == -2)
- return CC608SUB;
+ return SRTSUB;
if (track < 0)
return VOBSUB;
titleindex = ghb_settings_combo_int(ud->settings, "title");
if (track == -2)
{
- name = "Text";
+ name = "SRT";
goto done;
}
if (track == -1)
break;
case CC708SUB:
case CC608SUB:
- case SRTSUB:
name = "Text";
break;
+ case SRTSUB:
+ name = "SRT";
+ break;
default:
break;
}
return name;
}
+gchar*
+ghb_subtitle_track_lang(signal_user_data_t *ud, gint track)
+{
+ gint titleindex;
+
+ titleindex = ghb_settings_combo_int(ud->settings, "title");
+ if (titleindex < 0)
+ goto fail;
+ if (track == -1)
+ return ghb_get_user_audio_lang(ud, titleindex, 0);
+ if (track < 0)
+ goto fail;
+
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_subtitle_t * sub;
+
+ if (h_scan == NULL)
+ goto fail;
+
+ list = hb_get_titles( h_scan );
+ if( !hb_list_count( list ) )
+ {
+ /* No valid title, stop right there */
+ goto fail;
+ }
+ title = hb_list_item( list, titleindex );
+ if (title == NULL) // Bad titleindex
+ goto fail;
+ sub = hb_list_item( title->list_subtitle, track);
+ if (sub != NULL)
+ return g_strdup(sub->iso639_2);
+
+fail:
+ return g_strdup("und");
+}
gint
ghb_get_title_number(gint titleindex)
grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
}
- else if (container == HB_MUX_AVI)
- {
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, TRUE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
- grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
- }
- else if (container == HB_MUX_OGM)
- {
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, TRUE);
- }
gboolean allow_mono = TRUE;
gboolean allow_stereo = TRUE;
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);
(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);
}
}
gint
+ghb_get_best_audio_bitrate(gint acodec, gint br, gint channels)
+{
+ if (acodec & HB_ACODEC_FAAC)
+ {
+ int maxbr = channels * 80;
+ if (br > maxbr)
+ br = maxbr;
+ }
+ return br;
+}
+
+gint
ghb_get_best_mix(gint titleindex, gint track, gint acodec, gint mix)
{
hb_audio_config_t *audio = NULL;
{
allow_mono =
(audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
- (acodec != HB_ACODEC_LAME);
+ (acodec & ~HB_ACODEC_LAME);
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);
allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
allow_6ch =
(audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
- (acodec != HB_ACODEC_LAME) &&
+ (acodec & ~HB_ACODEC_LAME) &&
(layout == HB_INPUT_CH_LAYOUT_3F2R) &&
(audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
}
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
GtkTreeIter iter;
GtkListStore *store;
gint ii;
+ gchar *str;
g_debug("audio_samplerate_opts_set ()\n");
store = get_combo_box_store(builder, name);
// 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,
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);
}
}
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,
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);
+ }
+}
+
+static void
+srt_codeset_opts_set(GtkBuilder *builder, const gchar *name)
+{
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gint ii;
+
+ g_debug("srt_codeset_opts_set ()\n");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
+ for (ii = 0; ii < SRT_TABLE_SIZE; ii++)
+ {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, srt_codeset_table[ii],
+ 1, TRUE,
+ 2, srt_codeset_table[ii],
+ 3, (gdouble)ii,
+ 4, srt_codeset_table[ii],
+ -1);
}
+ GtkComboBoxEntry *cbe;
+
+ cbe = GTK_COMBO_BOX_ENTRY(GHB_WIDGET(builder, name));
+ //gtk_combo_box_entry_set_text_column(cbe, 0);
}
static void
gtk_list_store_clear(store);
for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
{
+ const gchar *lang;
+
+ if (ghb_language_table[ii].native_name[0] != 0)
+ lang = ghb_language_table[ii].native_name;
+ else
+ lang = ghb_language_table[ii].eng_name;
+
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, ghb_language_table[ii].eng_name,
+ 0, lang,
1, TRUE,
2, ghb_language_table[ii].iso639_2,
3, (gdouble)ii,
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,
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);
// 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,
{
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;
if (subtitle_opts.map) g_free(subtitle_opts.map);
if (count > 0)
{
- subtitle_opts.count = count;
- subtitle_opts.map = g_malloc((count)*sizeof(options_map_t));
+ subtitle_opts.count = count+1;
+ subtitle_opts.map = g_malloc((count+1)*sizeof(options_map_t));
}
else
{
- subtitle_opts.count = LANG_TABLE_SIZE;
- subtitle_opts.map = g_malloc((LANG_TABLE_SIZE)*sizeof(options_map_t));
+ subtitle_opts.count = LANG_TABLE_SIZE+1;
+ subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+1)*sizeof(options_map_t));
}
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, "Foreign Audio Search",
+ 1, TRUE,
+ 2, "-1",
+ 3, -1.0,
+ 4, "auto",
+ -1);
+ subtitle_opts.map[0].option = "Foreign Audio Search";
+ subtitle_opts.map[0].shortOpt = "-1";
+ subtitle_opts.map[0].ivalue = -1;
+ subtitle_opts.map[0].svalue = "auto";
if (count > 0)
{
if (options != NULL)
// 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);
- subtitle_opts.map[ii].option = options[ii];
- subtitle_opts.map[ii].shortOpt = index_str[ii];
- subtitle_opts.map[ii].ivalue = ii;
- subtitle_opts.map[ii].svalue = subtitle->iso639_2;
+ subtitle_opts.map[ii+1].option = options[ii];
+ subtitle_opts.map[ii+1].shortOpt = index_str[ii];
+ subtitle_opts.map[ii+1].ivalue = ii;
+ subtitle_opts.map[ii+1].svalue = subtitle->iso639_2;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
0, options[ii],
index_str_init(LANG_TABLE_SIZE-1);
for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
{
- subtitle_opts.map[ii].option = ghb_language_table[ii].eng_name;
- subtitle_opts.map[ii].shortOpt = index_str[ii];
- subtitle_opts.map[ii].ivalue = ii;
- subtitle_opts.map[ii].svalue = ghb_language_table[ii].iso639_2;
+ const gchar *lang;
+
+ if (ghb_language_table[ii].native_name[0] != 0)
+ lang = ghb_language_table[ii].native_name;
+ else
+ lang = ghb_language_table[ii].eng_name;
+
+ subtitle_opts.map[ii+1].option = lang;
+ subtitle_opts.map[ii+1].shortOpt = index_str[ii];
+ subtitle_opts.map[ii+1].ivalue = ii;
+ subtitle_opts.map[ii+1].svalue = ghb_language_table[ii].iso639_2;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, ghb_language_table[ii].eng_name,
+ 0, lang,
1, TRUE,
2, index_str[ii],
3, (gdouble)ii,
return titleindex;
}
+gchar*
+ghb_get_source_audio_lang(gint titleindex, gint track)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_audio_config_t * audio;
+ gchar *lang = NULL;
+
+ g_debug("ghb_lookup_1st_audio_lang ()\n");
+ if (h_scan == NULL)
+ return NULL;
+ list = hb_get_titles( h_scan );
+ title = (hb_title_t*)hb_list_item( list, titleindex );
+ if (title == NULL)
+ return NULL;
+ if (hb_list_count( title->list_audio ) <= track)
+ return NULL;
+
+ audio = hb_list_audio_config_item(title->list_audio, track);
+ if (audio == NULL)
+ return NULL;
+
+ lang = g_strdup(audio->lang.iso639_2);
+ 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))
{
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)))
{
}
}
}
+ try_acodec = fallback_acodec;
+ }
+ else
+ {
+ try_acodec = acodec;
}
if (track > -1)
{
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) &&
{
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)
{
}
}
}
+ try_acodec = fallback_acodec;
+ }
+ else
+ {
+ try_acodec = acodec;
}
if (track > -1)
{
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)
// 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;
}
gint
+ghb_find_cc_track(gint titleindex)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_subtitle_t * subtitle;
+ gint count, ii;
+
+ g_debug("ghb_find_cc_track ()\n");
+ if (h_scan == NULL) return -2;
+ list = hb_get_titles( h_scan );
+ title = (hb_title_t*)hb_list_item( list, titleindex );
+ if (title != NULL)
+ {
+ count = hb_list_count( title->list_subtitle );
+ // Try to find an item that matches the preferred language
+ for (ii = 0; ii < count; ii++)
+ {
+ subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
+ if (subtitle->source == CC608SUB || subtitle->source == CC708SUB)
+ return ii;
+ }
+ }
+ return -2;
+}
+
+gint
ghb_find_subtitle_track(
- gint titleindex,
- const gchar *lang,
- GHashTable *track_indices)
+ gint titleindex,
+ const gchar * lang,
+ gboolean burn,
+ gboolean force,
+ gint source,
+ GHashTable * track_indices)
{
hb_list_t * list;
hb_title_t * title;
used = g_malloc0(count * sizeof(gboolean));
g_hash_table_insert(track_indices, g_strdup(lang), used);
}
+ // Try to find an item that matches the preferred language and source
+ for (ii = 0; ii < count; ii++)
+ {
+ if (used[ii])
+ continue;
+
+ subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
+ if (source == subtitle->source &&
+ ((strcmp(lang, subtitle->iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
+ {
+ used[ii] = TRUE;
+ return ii;
+ }
+ }
// Try to find an item that matches the preferred language
for (ii = 0; ii < count; ii++)
{
continue;
subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
- if ((strcmp(lang, subtitle->iso639_2) == 0) ||
- (strcmp(lang, "und") == 0))
+ if (((burn || force) && (subtitle->source == VOBSUB)) &&
+ ((strcmp(lang, subtitle->iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
{
used[ii] = TRUE;
return ii;
}
}
+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)
{
return lookup_video_rate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_int(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_int(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else
{
return lookup_video_rate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_int(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_int(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else
{
return lookup_video_rate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_option(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_option(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else
{
return lookup_video_rate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_option(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_option(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else
{
audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
mix_opts_set(ud->builder, "AudioMixdown");
- language_opts_set(ud->builder, "SourceAudioLang");
+ language_opts_set(ud->builder, "SrtLanguage");
+ language_opts_set(ud->builder, "PreferredLanguage");
+ srt_codeset_opts_set(ud->builder, "SrtCodeset");
title_opts_set(ud->builder, "title");
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);
generic_opts_set(ud->builder, "LoggingLevel", &logging_opts);
+ generic_opts_set(ud->builder, "LogLongevity", &log_longevity_opts);
+ generic_opts_set(ud->builder, "check_updates", &appcast_update_opts);
generic_opts_set(ud->builder, "FileFormat", &container_opts);
generic_opts_set(ud->builder, "PictureDeinterlace", &deint_opts);
generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
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);
video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
else if (strcmp(name, "AudioMixdown") == 0)
mix_opts_set(ud->builder, "AudioMixdown");
- else if (strcmp(name, "SourceAudioLang") == 0)
- language_opts_set(ud->builder, "SourceAudioLang");
+ else if (strcmp(name, "SrtLanguage") == 0)
+ language_opts_set(ud->builder, "SrtLanguage");
+ else if (strcmp(name, "PreferredLanguage") == 0)
+ language_opts_set(ud->builder, "PreferredLanguage");
+ else if (strcmp(name, "SrtCodeset") == 0)
+ srt_codeset_opts_set(ud->builder, "SrtCodeset");
else if (strcmp(name, "title") == 0)
title_opts_set(ud->builder, "title");
else if (strcmp(name, "SubtitleTrack") == 0)
init_combo_box(builder, "AudioSamplerate");
init_combo_box(builder, "VideoFramerate");
init_combo_box(builder, "AudioMixdown");
- init_combo_box(builder, "SourceAudioLang");
+ init_combo_box(builder, "SrtLanguage");
+ init_combo_box(builder, "PreferredLanguage");
+ init_combo_box(builder, "SrtCodeset");
init_combo_box(builder, "title");
init_combo_box(builder, "AudioTrack");
for (ii = 0; combo_name_map[ii].name != NULL; ii++)
}
static const char * turbo_opts =
- "ref=1:subme=1:me=dia:analyse=none:trellis=0:"
- "no-fast-pskip=0:8x8dct=0:weightb=0";
+ "ref=1:subme=2:me=dia:analyse=none:trellis=0:"
+ "no-fast-pskip=0:8x8dct=0";
// Construct the x264 options string
// The result is allocated, so someone must free it at some point.
}
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;
asettings = ghb_array_get_nth(audio_list, ii);
acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
- if (acodec == HB_ACODEC_AC3)
+ if (acodec & HB_ACODEC_AC3)
return TRUE;
}
return FALSE;
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,
}
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;
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);
{
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);
GtkTreeIter iter;
GtkListStore *store;
gint ii;
+ gchar *str;
g_debug("audio_bitrate_opts_set ()\n");
store = get_combo_box_store(builder, 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);
}
}
}
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;
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)
{
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;
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));
tinfo->duration = title->duration;
tinfo->angle_count = title->angle_count;
+ tinfo->path = title->path;
+ tinfo->name = title->name;
+ tinfo->type = title->type;
return TRUE;
}
{
gboolean autoscale, keep_aspect, enable_keep_aspect;
gboolean enable_scale_width, enable_scale_height;
- gboolean enable_disp_width, enable_disp_height;
+ gboolean enable_disp_width, enable_disp_height, enable_par;
gint pic_par;
GtkWidget *widget;
enable_scale_width = !autoscale && (pic_par != 1);
enable_scale_height = !autoscale && (pic_par != 1);
enable_disp_width = (pic_par == 3) && !keep_aspect;
+ enable_par = (pic_par == 3) && !keep_aspect;
enable_disp_height = FALSE;
widget = GHB_WIDGET(ud->builder, "PictureModulus");
gtk_widget_set_sensitive(widget, enable_disp_width);
widget = GHB_WIDGET(ud->builder, "PictureDisplayHeight");
gtk_widget_set_sensitive(widget, enable_disp_height);
+ widget = GHB_WIDGET(ud->builder, "PicturePARWidth");
+ gtk_widget_set_sensitive(widget, enable_par);
+ widget = GHB_WIDGET(ud->builder, "PicturePARHeight");
+ gtk_widget_set_sensitive(widget, enable_par);
widget = GHB_WIDGET(ud->builder, "PictureKeepRatio");
gtk_widget_set_sensitive(widget, enable_keep_aspect);
widget = GHB_WIDGET(ud->builder, "autoscale");
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 ) )
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");
// The scaler crashes if the dimensions are not divisible by 2
// Align mod 2. And so does something in x264_encoder_headers()
job->anamorphic.modulus = mod;
+ job->anamorphic.par_width = title->pixel_aspect_width;
+ job->anamorphic.par_height = title->pixel_aspect_height;
+ job->anamorphic.dar_width = 0;
+ 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;
- if (max_width)
- job->maxWidth = max_width;
- if (max_height)
- job->maxHeight = max_height;
+ job->maxWidth = max_width;
+ job->maxHeight = max_height;
job->crop[0] = crop[0]; job->crop[1] = crop[1];
job->crop[2] = crop[2]; job->crop[3] = crop[3];
if (job->anamorphic.mode == 3 && !keep_aspect)
{
- gint dar_width, dar_height;
+ job->anamorphic.keep_display_aspect = 0;
if (mode & GHB_PIC_KEEP_PAR)
{
- par_width = ghb_settings_get_int(ud->settings,
- "PicturePARWidth");
- par_height = ghb_settings_get_int(ud->settings,
- "PicturePARHeight");
- dar_width = ((gdouble)width * par_width / par_height) + 0.5;
- dar_height = height;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(ud->settings, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(ud->settings, "PicturePARHeight");
}
else
{
- dar_width = ghb_settings_get_int(ud->settings,
- "PictureDisplayWidth");
- dar_height = ghb_settings_get_int(ud->settings,
- "PictureDisplayHeight");
+ job->anamorphic.dar_width =
+ ghb_settings_get_int(ud->settings,
+ "PictureDisplayWidth");
+ job->anamorphic.dar_height = height;
}
- job->anamorphic.dar_width = dar_width;
- job->anamorphic.dar_height = dar_height;
}
else
{
- job->anamorphic.dar_width = 0;
- job->anamorphic.dar_height = 0;
+ job->anamorphic.keep_display_aspect = 1;
}
hb_set_anamorphic_size( job, &width, &height,
&par_width, &par_height );
+ if (job->anamorphic.mode == 3 && !keep_aspect &&
+ mode & GHB_PIC_KEEP_PAR)
+ {
+ // hb_set_anamorphic_size reduces the par, which we
+ // don't want in this case because the user is
+ // explicitely specifying it.
+ par_width = ghb_settings_get_int(ud->settings,
+ "PicturePARWidth");
+ par_height = ghb_settings_get_int(ud->settings,
+ "PicturePARHeight");
+ }
}
else
{
}
ghb_ui_update(ud, "display_aspect", ghb_string_value(str));
g_free(str);
- ghb_ui_update(ud, "par_width", ghb_int64_value(par_width));
- ghb_ui_update(ud, "par_height", ghb_int64_value(par_height));
+ ghb_ui_update(ud, "PicturePARWidth", ghb_int64_value(par_width));
+ ghb_ui_update(ud, "PicturePARHeight", ghb_int64_value(par_height));
ghb_ui_update(ud, "PictureDisplayWidth", ghb_int64_value(disp_width));
ghb_ui_update(ud, "PictureDisplayHeight", ghb_int64_value(height));
busy = FALSE;
job->anamorphic.modulus = 2;
}
- gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
- gint decomb = ghb_settings_combo_int(settings, "PictureDecomb");
- job->deinterlace = (!decomb && deint == 0) ? 0 : 1;
-
- gboolean keep_aspect;
- keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
- if (job->anamorphic.mode == 3 && !keep_aspect)
+ gboolean decomb_deint = ghb_settings_get_boolean(settings, "PictureDecombDeinterlace");
+ if (decomb_deint)
{
- gint disp_width, disp_height;
- disp_width = ghb_settings_get_int(settings, "PictureDisplayWidth");
- disp_height = ghb_settings_get_int(settings, "PictureDisplayHeight");
- job->anamorphic.dar_width = disp_width;
- job->anamorphic.dar_height = disp_height;
+ gint decomb = ghb_settings_combo_int(settings, "PictureDecomb");
+ job->deinterlace = (decomb == 0) ? 0 : 1;
}
else
{
+ gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
+ job->deinterlace = (deint == 0) ? 0 : 1;
+ }
+
+ gboolean keep_aspect;
+ keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
+ if (job->anamorphic.mode)
+ {
+ job->anamorphic.par_width = job->title->pixel_aspect_width;
+ job->anamorphic.par_height = job->title->pixel_aspect_height;
job->anamorphic.dar_width = 0;
job->anamorphic.dar_height = 0;
+
+ if (job->anamorphic.mode == 3 && !keep_aspect)
+ {
+ job->anamorphic.keep_display_aspect = 0;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(settings, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(settings, "PicturePARHeight");
+ }
+ else
+ {
+ job->anamorphic.keep_display_aspect = 1;
+ }
}
}
gint index;
gchar *message;
- // deinte 4
+ gboolean decomb_deint = ghb_settings_get_boolean(ud->settings, "PictureDecombDeinterlace");
+ // deinte
index = ghb_settings_combo_int(ud->settings, "PictureDeinterlace");
- if (index == 1)
+ 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",
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",
}
g_free(str);
}
- // decomb 4
+ // decomb
index = ghb_settings_combo_int(ud->settings, "PictureDecomb");
- if (index == 1)
+ if (decomb_deint && index == 1)
{
str = ghb_settings_get_string(ud->settings, "PictureDecombCustom");
- if (!ghb_validate_filter_string(str, 7))
+ if (!ghb_validate_filter_string(str, -1))
{
message = g_strdup_printf(
"Invalid Decomb Settings:\n\n%s\n",
}
g_free(str);
}
- // denois 4
+ // denois
index = ghb_settings_combo_int(ud->settings, "PictureDenoise");
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",
mux = ghb_settings_combo_int(ud->settings, "FileFormat");
vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
- if ((mux == HB_MUX_MP4 || mux == HB_MUX_AVI) &&
- (vcodec == HB_VCODEC_THEORA))
+ if ((mux == HB_MUX_MP4) && (vcodec == HB_VCODEC_THEORA))
{
- // mp4|avi/theora combination is not supported.
+ // mp4/theora combination is not supported.
message = g_strdup_printf(
- "Theora is not supported in the MP4 and AVI containers.\n\n"
+ "Theora is not supported in the MP4 container.\n\n"
"You should choose a different video codec or container.\n"
"If you continue, FFMPEG will be chosen for you.");
if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
const GValue *slist, *settings;
- gint count, ii, track, source;
+ gint count, ii, source;
gboolean burned, one_burned = FALSE;
slist = ghb_settings_get_value(ud->settings, "subtitle_list");
for (ii = 0; ii < count; ii++)
{
settings = ghb_array_get_nth(slist, ii);
- track = ghb_settings_combo_int(settings, "SubtitleTrack");
+ source = ghb_settings_get_int(settings, "SubtitleSource");
burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
- source = ghb_subtitle_track_source(ud, track);
if (burned && one_burned)
{
// MP4 can only handle burned vobsubs. make sure there isn't
"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"))
+ if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message,
+ "Cancel", "Continue"))
{
g_free(message);
return FALSE;
g_free(message);
break;
}
+ if (source == SRTSUB)
+ {
+ gchar *filename;
+
+ filename = ghb_settings_get_string(settings, "SrtFile");
+ if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+ {
+ message = g_strdup_printf(
+ "Srt file does not exist or not a regular file.\n\n"
+ "You should choose a valid file.\n"
+ "If you continue, this subtitle will be ignored.");
+ if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message,
+ "Cancel", "Continue"))
+ {
+ g_free(message);
+ return FALSE;
+ }
+ g_free(message);
+ break;
+ }
+ }
}
return TRUE;
}
+gint
+ghb_select_audio_codec(signal_user_data_t *ud, gint track)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_audio_config_t *audio;
+
+ if (h_scan == NULL) return -1;
+ list = hb_get_titles( h_scan );
+ if( !hb_list_count( list ) )
+ {
+ return -1;
+ }
+
+ gint titleindex;
+
+ titleindex = ghb_settings_combo_int(ud->settings, "title");
+ title = hb_list_item( list, titleindex );
+ if (title == NULL) return -1;
+
+ gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
+
+ if (track < 0 || track >= hb_list_count(title->list_audio))
+ return -1;
+
+ audio = (hb_audio_config_t *) hb_list_audio_config_item(
+ title->list_audio, track );
+ if (mux == HB_MUX_MP4)
+ {
+ if (audio->in.codec == HB_ACODEC_AC3)
+ return audio->in.codec;
+ else
+ return HB_ACODEC_FAAC;
+ }
+ else
+ {
+ if (audio->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA)
+ return audio->in.codec;
+ else
+ return HB_ACODEC_LAME;
+ }
+}
+
+const gchar*
+ghb_select_audio_codec_str(signal_user_data_t *ud, gint track)
+{
+ gint acodec, ii;
+
+ acodec = ghb_select_audio_codec(ud, track);
+ for (ii = 0; ii < acodec_opts.count; ii++)
+ {
+ if (acodec_opts.map[ii].ivalue == acodec)
+ return acodec_opts.map[ii].option;
+ }
+ return "Unknown";
+}
+
gboolean
ghb_validate_audio(signal_user_data_t *ud)
{
asettings = ghb_array_get_nth(audio_list, ii);
gint track = ghb_settings_combo_int(asettings, "AudioTrack");
gint codec = ghb_settings_combo_int(asettings, "AudioEncoder");
+ if (codec == HB_ACODEC_MASK)
+ continue;
+
taudio = (hb_audio_config_t *) hb_list_audio_config_item(
title->list_audio, track );
if (!(taudio->in.codec & codec) &&
return FALSE;
}
g_free(message);
- if (mux == HB_MUX_AVI)
+ if (mux == HB_MUX_MKV)
{
codec = HB_ACODEC_LAME;
}
{
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;
codec = HB_ACODEC_FAAC;
}
}
- else if (mux == HB_MUX_AVI)
- {
- mux_s = "AVI";
- // avi/faac|vorbis combination is not supported.
- if (codec == HB_ACODEC_FAAC)
- {
- a_unsup = "FAAC";
- codec = HB_ACODEC_LAME;
- }
- if (codec == HB_ACODEC_VORBIS)
- {
- a_unsup = "Vorbis";
- codec = HB_ACODEC_LAME;
- }
- }
- else if (mux == HB_MUX_OGM)
- {
- mux_s = "OGM";
- // avi/faac|vorbis combination is not supported.
- if (codec == HB_ACODEC_FAAC)
- {
- a_unsup = "FAAC";
- codec = HB_ACODEC_VORBIS;
- }
- if (codec == HB_ACODEC_AC3)
- {
- a_unsup = "AC-3";
- codec = HB_ACODEC_VORBIS;
- }
- if (codec == HB_ACODEC_DCA)
- {
- a_unsup = "DTS";
- codec = HB_ACODEC_VORBIS;
- }
- }
if (a_unsup)
{
message = g_strdup_printf(
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");
gboolean allow_6ch = TRUE;
allow_mono =
(taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
- (codec != HB_ACODEC_LAME);
+ (codec & ~HB_ACODEC_LAME);
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);
allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
allow_6ch =
(taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
- (codec != HB_ACODEC_LAME) &&
+ (codec & ~HB_ACODEC_LAME) &&
(layout == HB_INPUT_CH_LAYOUT_3F2R) &&
(taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
job = title->job;
if (job == NULL) return;
+ job->angle = ghb_settings_get_int(js, "angle");
job->start_at_preview = ghb_settings_get_int(js, "start_frame") + 1;
if (job->start_at_preview)
{
}
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;
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)
{
job->crop[3] = ghb_settings_get_int(js, "PictureRightCrop");
+ gboolean decomb_deint = ghb_settings_get_boolean(js, "PictureDecombDeinterlace");
gint decomb = ghb_settings_combo_int(js, "PictureDecomb");
gint deint = ghb_settings_combo_int(js, "PictureDeinterlace");
- if (!decomb)
+ if (!decomb_deint)
job->deinterlace = (deint != 0) ? 1 : 0;
else
job->deinterlace = 0;
job->grayscale = ghb_settings_get_boolean(js, "VideoGrayScale");
+ gboolean keep_aspect;
+ keep_aspect = ghb_settings_get_boolean(js, "PictureKeepRatio");
job->anamorphic.mode = ghb_settings_combo_int(js, "PicturePAR");
job->anamorphic.modulus = ghb_settings_combo_int(js, "PictureModulus");
+ if (job->anamorphic.mode)
+ {
+ job->anamorphic.par_width = title->pixel_aspect_width;
+ job->anamorphic.par_height = title->pixel_aspect_height;
+ job->anamorphic.dar_width = 0;
+ job->anamorphic.dar_height = 0;
+
+ if (job->anamorphic.mode == 3 && !keep_aspect)
+ {
+ job->anamorphic.keep_display_aspect = 0;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(js, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(js, "PicturePARHeight");
+ }
+ else
+ {
+ job->anamorphic.keep_display_aspect = 1;
+ }
+ }
/* Add selected filters */
job->filters = hb_list_init();
hb_filter_detelecine.settings = detel_str;
hb_list_add( job->filters, &hb_filter_detelecine );
}
- if ( decomb )
+ if ( decomb_deint && decomb )
{
if (decomb != 1)
{
job->height = ghb_settings_get_int(js, "scale_height");
job->vcodec = ghb_settings_combo_int(js, "VideoEncoder");
- if ((job->mux == HB_MUX_MP4 || job->mux == HB_MUX_AVI) &&
- (job->vcodec == HB_VCODEC_THEORA))
+ if ((job->mux == HB_MUX_MP4 ) && (job->vcodec == HB_VCODEC_THEORA))
{
- // mp4|avi/theora combination is not supported.
+ // mp4/theora combination is not supported.
job->vcodec = HB_VCODEC_FFMPEG;
}
if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
job->cfr = 1;
}
- // AVI container does not support variable frame rate.
- // OGM supports variable frame rate, but bases all timing on
- // DTS, which breaks when b-frames are used since it is
- // impossible to reconstruct PTS from DTS when the framerate
- // is variable.
- if (job->mux == HB_MUX_AVI || job->mux == HB_MUX_OGM)
- {
- job->cfr = 1;
- }
-
const GValue *audio_list;
gint count, ii;
gint tcount = 0;
title->list_audio, audio.in.track );
if (audio.out.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
{
- if (!(taudio->in.codec & audio.out.codec))
+ if (!(taudio->in.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)))
{
- // Not supported. AC3 is passthrough only, so input must be AC3
- if (job->mux == HB_MUX_AVI)
+ // Not supported.
+ // AC3/DTS is passthrough only, so input must be AC3/DTS
+ if (job->mux == HB_MUX_MKV)
{
audio.out.codec = HB_ACODEC_LAME;
}
}
}
if ((job->mux == HB_MUX_MP4) &&
- ((audio.out.codec == HB_ACODEC_LAME) ||
- (audio.out.codec == HB_ACODEC_VORBIS)))
+ ((audio.out.codec & HB_ACODEC_LAME) ||
+ (audio.out.codec & HB_ACODEC_DCA) ||
+ (audio.out.codec & HB_ACODEC_VORBIS)))
{
- // mp4/mp3|vorbis combination is not supported.
+ // mp4/mp3|dts|vorbis combination is not supported.
audio.out.codec = HB_ACODEC_FAAC;
}
- if ((job->mux == HB_MUX_AVI) &&
- ((audio.out.codec == HB_ACODEC_FAAC) ||
- (audio.out.codec == HB_ACODEC_VORBIS)))
- {
- // avi/faac|vorbis combination is not supported.
- audio.out.codec = HB_ACODEC_LAME;
- }
- if ((job->mux == HB_MUX_OGM) &&
- ((audio.out.codec == HB_ACODEC_FAAC) ||
- (audio.out.codec == HB_ACODEC_AC3) ||
- (audio.out.codec == HB_ACODEC_DCA)))
- {
- // ogm/faac|ac3 combination is not supported.
- audio.out.codec = HB_ACODEC_VORBIS;
- }
audio.out.dynamic_range_compression =
ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
+ if (audio.out.dynamic_range_compression < 1.0)
+ audio.out.dynamic_range_compression = 0.0;
+
// It would be better if this were done in libhb for us, but its not yet.
- if (audio.out.codec == HB_ACODEC_AC3 || audio.out.codec == HB_ACODEC_DCA)
+ if (audio.out.codec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
{
audio.out.mixdown = 0;
}
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.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
dest_str = ghb_settings_get_string(js, "destination");
job->file = dest_str;
- job->crf = ghb_settings_get_boolean(js, "constant_rate_factor");
- // TODO: libhb holds onto a reference to the x264opts and is not
- // finished with it until encoding the job is done. But I can't
- // find a way to get at the job before it is removed in order to
- // free up the memory I am allocating here.
- // The short story is THIS LEAKS.
- x264opts = ghb_build_x264opts_string(js);
-
- if( x264opts != NULL && *x264opts != '\0' )
- {
- job->x264opts = x264opts;
- }
- else /*avoids a bus error crash when options aren't specified*/
- {
- job->x264opts = NULL;
- }
const GValue *subtitle_list;
gint subtitle;
gboolean force, burned, def, one_burned = FALSE;
- job->select_subtitle = NULL;
- if (ghb_settings_get_boolean(js, "SubtitleForeignSearch"))
- {
- force = ghb_settings_get_boolean(js, "SubtitleForeignForced");
- burned = ghb_settings_get_boolean(js, "SubtitleForeignBurned");
- def = ghb_settings_get_boolean(js, "SubtitleForeignDefaultTrack");
-
- if (burned || job->mux != HB_MUX_MP4)
- {
- if (!burned && job->mux == HB_MUX_MKV)
- {
- job->select_subtitle_config.dest = PASSTHRUSUB;
- }
- if (burned)
- one_burned = TRUE;
- job->select_subtitle_config.force = force;
- job->select_subtitle_config.default_track = def;
- job->indepth_scan = 1;
- job->select_subtitle = malloc(sizeof(hb_subtitle_t*));
- *job->select_subtitle = NULL;
- }
- }
+ ghb_settings_set_boolean(js, "subtitle_scan", FALSE);
subtitle_list = ghb_settings_get_value(js, "subtitle_list");
count = ghb_array_len(subtitle_list);
for (ii = 0; ii < count; ii++)
{
GValue *ssettings;
+ gint source;
ssettings = ghb_array_get_nth(subtitle_list, ii);
- subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
force = ghb_settings_get_boolean(ssettings, "SubtitleForced");
burned = ghb_settings_get_boolean(ssettings, "SubtitleBurned");
def = ghb_settings_get_boolean(ssettings, "SubtitleDefaultTrack");
+ source = ghb_settings_get_int(ssettings, "SubtitleSource");
+
+ if (source == SRTSUB)
+ {
+ hb_subtitle_config_t sub_config;
+ gchar *filename, *lang, *code;
- if (subtitle >= 0)
+ filename = ghb_settings_get_string(ssettings, "SrtFile");
+ if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+ {
+ continue;
+ }
+ sub_config.offset = ghb_settings_get_int(ssettings, "SrtOffset");
+ lang = ghb_settings_get_string(ssettings, "SrtLanguage");
+ code = ghb_settings_get_string(ssettings, "SrtCodeset");
+ strncpy(sub_config.src_filename, filename, 128);
+ strncpy(sub_config.src_codeset, code, 40);
+ sub_config.force = 0;
+ sub_config.dest = PASSTHRUSUB;
+ sub_config.default_track = def;
+
+ hb_srt_add( job, &sub_config, lang);
+
+ g_free(filename);
+ g_free(lang);
+ g_free(code);
+ continue;
+ }
+
+ subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
+ if (subtitle == -1)
+ {
+ if (!burned && job->mux == HB_MUX_MKV)
+ {
+ 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
+ if (one_burned)
+ continue;
+ job->select_subtitle_config.dest = RENDERSUB;
+ one_burned = TRUE;
+ }
+ job->select_subtitle_config.force = force;
+ job->select_subtitle_config.default_track = def;
+ job->indepth_scan = 1;
+ ghb_settings_set_boolean(js, "subtitle_scan", TRUE);
+ }
+ else if (subtitle >= 0)
{
hb_subtitle_t * subt;
hb_subtitle_config_t sub_config;
}
}
+ // TODO: libhb holds onto a reference to the x264opts and is not
+ // finished with it until encoding the job is done. But I can't
+ // find a way to get at the job before it is removed in order to
+ // free up the memory I am allocating here.
+ // The short story is THIS LEAKS.
+ x264opts = ghb_build_x264opts_string(js);
+
+ if( *x264opts == '\0' )
+ {
+ g_free(x264opts);
+ x264opts = NULL;
+ }
+
if (job->indepth_scan == 1)
{
// Subtitle scan. Look for subtitle matching audio language
- char *x264opts_tmp;
/*
* When subtitle scan is enabled do a fast pre-scan job
*/
job->pass = -1;
job->indepth_scan = 1;
-
- x264opts_tmp = job->x264opts;
job->x264opts = NULL;
-
/*
* Add the pre-scan job
*/
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
- //if (job->x264opts != NULL)
- // g_free(job->x264opts);
-
- job->x264opts = x264opts_tmp;
}
if( ghb_settings_get_boolean(js, "VideoTwoPass") &&
* for the second pass and then off again for the
* second.
*/
- hb_subtitle_t **subtitle_tmp = job->select_subtitle;
- job->select_subtitle = NULL;
job->pass = 1;
job->indepth_scan = 0;
- gchar *x264opts2 = NULL;
- if (x264opts)
- {
- x264opts2 = g_strdup(x264opts);
- }
+
/*
* If turbo options have been selected then append them
* to the x264opts now (size includes one ':' and the '\0')
*/
if( ghb_settings_get_boolean(js, "VideoTurboTwoPass") )
{
- char *tmp_x264opts;
+ gchar *tmp_x264opts;
+ gchar *extra_opts;
+ gint badapt;
+ badapt = ghb_lookup_badapt(x264opts);
+ if (badapt == 2)
+ {
+ extra_opts = g_strdup_printf("%s", turbo_opts);
+ }
+ else
+ {
+ extra_opts = g_strdup_printf("%s:weightb=0", turbo_opts);
+ }
+
if ( x264opts )
{
- tmp_x264opts = g_strdup_printf("%s:%s", x264opts, turbo_opts);
- g_free(x264opts);
+ tmp_x264opts = g_strdup_printf("%s:%s", x264opts, extra_opts);
}
else
{
* No x264opts to modify, but apply the turbo options
* anyway as they may be modifying defaults
*/
- tmp_x264opts = g_strdup_printf("%s", turbo_opts);
+ tmp_x264opts = g_strdup_printf("%s", extra_opts);
}
- x264opts = tmp_x264opts;
+ g_free(extra_opts);
+ job->x264opts = tmp_x264opts;
+ }
+ else
+ {
job->x264opts = x264opts;
}
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
//if (job->x264opts != NULL)
// g_free(job->x264opts);
- job->select_subtitle = subtitle_tmp;
job->pass = 2;
/*
* On the second pass we turn off subtitle scan so that we
* attribute of the job).
*/
job->indepth_scan = 0;
- job->x264opts = x264opts2;
+ job->x264opts = x264opts;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
//if (job->x264opts != NULL)
}
else
{
+ job->x264opts = x264opts;
job->indepth_scan = 0;
job->pass = 0;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
if( s.state == HB_STATE_PAUSED )
{
- hb_resume( h_queue );
+ hb_status.queue.state &= ~GHB_STATE_PAUSED;
+ hb_resume( h_queue );
}
else
{
- hb_pause( h_queue );
+ hb_status.queue.state |= GHB_STATE_PAUSED;
+ hb_pause( h_queue );
}
}
w *= (gdouble)dstWidth / orig_w;
h *= (gdouble)dstHeight / orig_h;
}
- g_debug("scaled %d x %d", dstWidth, dstHeight);
GdkPixbuf *scaled_preview;
scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
if (ghb_settings_get_boolean(settings, "show_crop"))