1 /***************************************************************************
4 * Fri Mar 28 10:38:44 2008
5 * Copyright 2008 John Stebbins
6 * <john at stebbins dot name>
7 ****************************************************************************/
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
28 #include "hbversion.h"
30 #include <glib/gstdio.h>
31 #include "hb-backend.h"
33 #include "callbacks.h"
38 const gchar *shortOpt;
51 static options_map_t d_container_opts[] =
53 {"MKV", "mkv", HB_MUX_MKV, 0.0, "mkv"},
54 {"MP4", "mp4", HB_MUX_MP4, 0.0, "mp4"},
55 {"M4V", "m4v", HB_MUX_MP4, 0.0, "m4v"},
56 {"AVI", "avi", HB_MUX_AVI, 0.0, "avi"},
57 {"OGM", "ogm", HB_MUX_OGM, 0.0, "ogm"},
59 combo_opts_t container_opts =
61 sizeof(d_container_opts)/sizeof(options_map_t),
65 static options_map_t d_deint_opts[] =
67 {"None", "none", 0, 0.0, ""},
68 {"Fast", "fast", 1, 0.0, "-1:-1:-1:0:1"},
69 {"Slow", "slow", 2, 0.0, "2:-1:-1:0:1"},
70 {"Slower", "slower", 3, 0.0, "0:-1:-1:0:1"},
72 combo_opts_t deint_opts =
74 sizeof(d_deint_opts)/sizeof(options_map_t),
78 static options_map_t d_denoise_opts[] =
80 {"None", "none", 0, 0.0, ""},
81 {"Weak", "weak", 1, 0.0, "2:1:2:3"},
82 {"Medium", "medium", 2, 0.0, "3:2:2:3"},
83 {"Strong", "strong", 3, 0.0, "7:7:5:5"},
85 combo_opts_t denoise_opts =
87 sizeof(d_denoise_opts)/sizeof(options_map_t),
91 static options_map_t d_vcodec_opts[] =
93 {"H.264 (x264)", "x264", HB_VCODEC_X264, 0.0, ""},
94 {"MPEG-4 (XviD)", "xvid", HB_VCODEC_XVID, 0.0, ""},
95 {"MPEG-4 (FFMPEG)", "ffmpeg", HB_VCODEC_FFMPEG, 0.0, ""},
96 {"Theora", "theora", HB_VCODEC_THEORA, 0.0, ""},
98 combo_opts_t vcodec_opts =
100 sizeof(d_vcodec_opts)/sizeof(options_map_t),
104 static options_map_t d_acodec_opts[] =
106 {"AAC (faac)", "faac", HB_ACODEC_FAAC, 0.0, ""},
107 {"MP3 (lame)", "lame", HB_ACODEC_LAME, 0.0, ""},
108 {"Vorbis", "vorbis", HB_ACODEC_VORBIS, 0.0, ""},
109 {"AC3 (pass-thru)", "ac3", HB_ACODEC_AC3, 0.0, ""},
111 combo_opts_t acodec_opts =
113 sizeof(d_acodec_opts)/sizeof(options_map_t),
117 static options_map_t d_pref_acodec_opts[] =
119 {"None", "none", 0, 0.0, ""},
120 {"AAC (faac)", "faac", HB_ACODEC_FAAC, 0.0, ""},
121 {"MP3 (lame)", "lame", HB_ACODEC_LAME, 0.0, ""},
122 {"Vorbis", "vorbis", HB_ACODEC_VORBIS, 0.0, ""},
123 {"AC3 (pass-thru)", "ac3", HB_ACODEC_AC3, 0.0, ""},
125 combo_opts_t pref_acodec_opts =
127 sizeof(d_pref_acodec_opts)/sizeof(options_map_t),
131 static options_map_t d_source_acodec_opts[] =
133 {"AC3", "ac3", HB_ACODEC_AC3, 0.0, ""},
134 {"DTS", "dca", HB_ACODEC_DCA, 0.0, ""},
135 {"MP2", "mpga", HB_ACODEC_MPGA, 0.0, ""},
136 {"LPCM", "lpcm", HB_ACODEC_LPCM, 0.0, ""},
138 combo_opts_t source_acodec_opts =
140 sizeof(d_source_acodec_opts)/sizeof(options_map_t),
144 static options_map_t d_direct_opts[] =
146 {"None", "none", 0, 0.0, "none"},
147 {"Spatial", "spatial", 1, 0.0, "spatial"},
148 {"Temporal", "temporal", 2, 0.0, "temporal"},
149 {"Automatic", "auto", 3, 0.0, "auto"},
151 combo_opts_t direct_opts =
153 sizeof(d_direct_opts)/sizeof(options_map_t),
157 static options_map_t d_me_opts[] =
159 {"Diamond", "dia", 0, 0.0, "dia"},
160 {"Hexagon", "hex", 1, 0.0, "hex"},
161 {"Uneven Multi-Hexagon", "umh", 2, 0.0, "umh"},
162 {"Exhaustive", "esa", 3, 0.0, "esa"},
164 combo_opts_t me_opts =
166 sizeof(d_me_opts)/sizeof(options_map_t),
170 static options_map_t d_subme_opts[] =
172 {"1", "1", 1, 0.0, "1"},
173 {"2", "2", 2, 0.0, "2"},
174 {"3", "3", 3, 0.0, "3"},
175 {"4", "4", 4, 0.0, "4"},
176 {"5", "5", 5, 0.0, "5"},
177 {"6", "6", 6, 0.0, "6"},
178 {"7", "7", 7, 0.0, "7"},
180 combo_opts_t subme_opts =
182 sizeof(d_subme_opts)/sizeof(options_map_t),
186 static options_map_t d_analyse_opts[] =
188 {"Some", "some", 0, 0.0, "some"},
189 {"None", "none", 1, 0.0, "none"},
190 {"All", "all", 2, 0.0, "all:8x8dct=1"},
192 combo_opts_t analyse_opts =
194 sizeof(d_analyse_opts)/sizeof(options_map_t),
198 static options_map_t d_trellis_opts[] =
200 {"Disabled", "off", 0, 0.0, ""},
201 {"Final Macro Block", "fmb", 1, 0.0, ""},
202 {"Always", "always", 2, 0.0, ""},
204 combo_opts_t trellis_opts =
206 sizeof(d_trellis_opts)/sizeof(options_map_t),
210 typedef struct iso639_lang_t
212 char * eng_name; /* Description in English */
213 char * native_name; /* Description in native language */
214 char * iso639_1; /* ISO-639-1 (2 characters) code */
215 char * iso639_2; /* ISO-639-2/t (3 character) code */
216 char * iso639_2b; /* ISO-639-2/b code (if different from above) */
219 static const iso639_lang_t language_table[] =
221 { "Any", "", "zz", "und" },
222 { "Afar", "", "aa", "aar" },
223 { "Abkhazian", "", "ab", "abk" },
224 { "Afrikaans", "", "af", "afr" },
225 { "Akan", "", "ak", "aka" },
226 { "Albanian", "", "sq", "sqi", "alb" },
227 { "Amharic", "", "am", "amh" },
228 { "Arabic", "", "ar", "ara" },
229 { "Aragonese", "", "an", "arg" },
230 { "Armenian", "", "hy", "hye", "arm" },
231 { "Assamese", "", "as", "asm" },
232 { "Avaric", "", "av", "ava" },
233 { "Avestan", "", "ae", "ave" },
234 { "Aymara", "", "ay", "aym" },
235 { "Azerbaijani", "", "az", "aze" },
236 { "Bashkir", "", "ba", "bak" },
237 { "Bambara", "", "bm", "bam" },
238 { "Basque", "", "eu", "eus", "baq" },
239 { "Belarusian", "", "be", "bel" },
240 { "Bengali", "", "bn", "ben" },
241 { "Bihari", "", "bh", "bih" },
242 { "Bislama", "", "bi", "bis" },
243 { "Bosnian", "", "bs", "bos" },
244 { "Breton", "", "br", "bre" },
245 { "Bulgarian", "", "bg", "bul" },
246 { "Burmese", "", "my", "mya", "bur" },
247 { "Catalan", "", "ca", "cat" },
248 { "Chamorro", "", "ch", "cha" },
249 { "Chechen", "", "ce", "che" },
250 { "Chinese", "", "zh", "zho", "chi" },
251 { "Church Slavic", "", "cu", "chu" },
252 { "Chuvash", "", "cv", "chv" },
253 { "Cornish", "", "kw", "cor" },
254 { "Corsican", "", "co", "cos" },
255 { "Cree", "", "cr", "cre" },
256 { "Czech", "", "cs", "ces", "cze" },
257 { "Danish", "Dansk", "da", "dan" },
258 { "Divehi", "", "dv", "div" },
259 { "Dutch", "Nederlands", "nl", "nld", "dut" },
260 { "Dzongkha", "", "dz", "dzo" },
261 { "English", "English", "en", "eng" },
262 { "Esperanto", "", "eo", "epo" },
263 { "Estonian", "", "et", "est" },
264 { "Ewe", "", "ee", "ewe" },
265 { "Faroese", "", "fo", "fao" },
266 { "Fijian", "", "fj", "fij" },
267 { "Finnish", "Suomi", "fi", "fin" },
268 { "French", "Francais", "fr", "fra", "fre" },
269 { "Western Frisian", "", "fy", "fry" },
270 { "Fulah", "", "ff", "ful" },
271 { "Georgian", "", "ka", "kat", "geo" },
272 { "German", "Deutsch", "de", "deu", "ger" },
273 { "Gaelic (Scots)", "", "gd", "gla" },
274 { "Irish", "", "ga", "gle" },
275 { "Galician", "", "gl", "glg" },
276 { "Manx", "", "gv", "glv" },
277 { "Greek, Modern", "", "el", "ell", "gre" },
278 { "Guarani", "", "gn", "grn" },
279 { "Gujarati", "", "gu", "guj" },
280 { "Haitian", "", "ht", "hat" },
281 { "Hausa", "", "ha", "hau" },
282 { "Hebrew", "", "he", "heb" },
283 { "Herero", "", "hz", "her" },
284 { "Hindi", "", "hi", "hin" },
285 { "Hiri Motu", "", "ho", "hmo" },
286 { "Hungarian", "Magyar", "hu", "hun" },
287 { "Igbo", "", "ig", "ibo" },
288 { "Icelandic", "Islenska", "is", "isl", "ice" },
289 { "Ido", "", "io", "ido" },
290 { "Sichuan Yi", "", "ii", "iii" },
291 { "Inuktitut", "", "iu", "iku" },
292 { "Interlingue", "", "ie", "ile" },
293 { "Interlingua", "", "ia", "ina" },
294 { "Indonesian", "", "id", "ind" },
295 { "Inupiaq", "", "ik", "ipk" },
296 { "Italian", "Italiano", "it", "ita" },
297 { "Javanese", "", "jv", "jav" },
298 { "Japanese", "", "ja", "jpn" },
299 { "Kalaallisut", "", "kl", "kal" },
300 { "Kannada", "", "kn", "kan" },
301 { "Kashmiri", "", "ks", "kas" },
302 { "Kanuri", "", "kr", "kau" },
303 { "Kazakh", "", "kk", "kaz" },
304 { "Central Khmer", "", "km", "khm" },
305 { "Kikuyu", "", "ki", "kik" },
306 { "Kinyarwanda", "", "rw", "kin" },
307 { "Kirghiz", "", "ky", "kir" },
308 { "Komi", "", "kv", "kom" },
309 { "Kongo", "", "kg", "kon" },
310 { "Korean", "", "ko", "kor" },
311 { "Kuanyama", "", "kj", "kua" },
312 { "Kurdish", "", "ku", "kur" },
313 { "Lao", "", "lo", "lao" },
314 { "Latin", "", "la", "lat" },
315 { "Latvian", "", "lv", "lav" },
316 { "Limburgan", "", "li", "lim" },
317 { "Lingala", "", "ln", "lin" },
318 { "Lithuanian", "", "lt", "lit" },
319 { "Luxembourgish", "", "lb", "ltz" },
320 { "Luba-Katanga", "", "lu", "lub" },
321 { "Ganda", "", "lg", "lug" },
322 { "Macedonian", "", "mk", "mkd", "mac" },
323 { "Marshallese", "", "mh", "mah" },
324 { "Malayalam", "", "ml", "mal" },
325 { "Maori", "", "mi", "mri", "mao" },
326 { "Marathi", "", "mr", "mar" },
327 { "Malay", "", "ms", "msa", "msa" },
328 { "Malagasy", "", "mg", "mlg" },
329 { "Maltese", "", "mt", "mlt" },
330 { "Moldavian", "", "mo", "mol" },
331 { "Mongolian", "", "mn", "mon" },
332 { "Nauru", "", "na", "nau" },
333 { "Navajo", "", "nv", "nav" },
334 { "Ndebele, South", "", "nr", "nbl" },
335 { "Ndebele, North", "", "nd", "nde" },
336 { "Ndonga", "", "ng", "ndo" },
337 { "Nepali", "", "ne", "nep" },
338 { "Norwegian Nynorsk", "", "nn", "nno" },
339 { "Norwegian Bokmål", "", "nb", "nob" },
340 { "Norwegian", "Norsk", "no", "nor" },
341 { "Chichewa; Nyanja", "", "ny", "nya" },
342 { "Occitan", "", "oc", "oci" },
343 { "Ojibwa", "", "oj", "oji" },
344 { "Oriya", "", "or", "ori" },
345 { "Oromo", "", "om", "orm" },
346 { "Ossetian", "", "os", "oss" },
347 { "Panjabi", "", "pa", "pan" },
348 { "Persian", "", "fa", "fas", "per" },
349 { "Pali", "", "pi", "pli" },
350 { "Polish", "", "pl", "pol" },
351 { "Portuguese", "Portugues", "pt", "por" },
352 { "Pushto", "", "ps", "pus" },
353 { "Quechua", "", "qu", "que" },
354 { "Romansh", "", "rm", "roh" },
355 { "Romanian", "", "ro", "ron", "rum" },
356 { "Rundi", "", "rn", "run" },
357 { "Russian", "", "ru", "rus" },
358 { "Sango", "", "sg", "sag" },
359 { "Sanskrit", "", "sa", "san" },
360 { "Serbian", "", "sr", "srp", "scc" },
361 { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
362 { "Sinhala", "", "si", "sin" },
363 { "Slovak", "", "sk", "slk", "slo" },
364 { "Slovenian", "", "sl", "slv" },
365 { "Northern Sami", "", "se", "sme" },
366 { "Samoan", "", "sm", "smo" },
367 { "Shona", "", "sn", "sna" },
368 { "Sindhi", "", "sd", "snd" },
369 { "Somali", "", "so", "som" },
370 { "Sotho, Southern", "", "st", "sot" },
371 { "Spanish", "Espanol", "es", "spa" },
372 { "Sardinian", "", "sc", "srd" },
373 { "Swati", "", "ss", "ssw" },
374 { "Sundanese", "", "su", "sun" },
375 { "Swahili", "", "sw", "swa" },
376 { "Swedish", "Svenska", "sv", "swe" },
377 { "Tahitian", "", "ty", "tah" },
378 { "Tamil", "", "ta", "tam" },
379 { "Tatar", "", "tt", "tat" },
380 { "Telugu", "", "te", "tel" },
381 { "Tajik", "", "tg", "tgk" },
382 { "Tagalog", "", "tl", "tgl" },
383 { "Thai", "", "th", "tha" },
384 { "Tibetan", "", "bo", "bod", "tib" },
385 { "Tigrinya", "", "ti", "tir" },
386 { "Tonga", "", "to", "ton" },
387 { "Tswana", "", "tn", "tsn" },
388 { "Tsonga", "", "ts", "tso" },
389 { "Turkmen", "", "tk", "tuk" },
390 { "Turkish", "", "tr", "tur" },
391 { "Twi", "", "tw", "twi" },
392 { "Uighur", "", "ug", "uig" },
393 { "Ukrainian", "", "uk", "ukr" },
394 { "Urdu", "", "ur", "urd" },
395 { "Uzbek", "", "uz", "uzb" },
396 { "Venda", "", "ve", "ven" },
397 { "Vietnamese", "", "vi", "vie" },
398 { "Volapük", "", "vo", "vol" },
399 { "Welsh", "", "cy", "cym", "wel" },
400 { "Walloon", "", "wa", "wln" },
401 { "Wolof", "", "wo", "wol" },
402 { "Xhosa", "", "xh", "xho" },
403 { "Yiddish", "", "yi", "yid" },
404 { "Yoruba", "", "yo", "yor" },
405 { "Zhuang", "", "za", "zha" },
406 { "Zulu", "", "zu", "zul" },
408 #define LANG_TABLE_SIZE (sizeof(language_table)/ sizeof(iso639_lang_t))
411 del_tree(const gchar *name, gboolean del_top)
415 if (g_file_test(name, G_FILE_TEST_IS_DIR))
417 GDir *gdir = g_dir_open(name, 0, NULL);
418 file = g_dir_read_name(gdir);
422 path = g_strdup_printf("%s/%s", name, file);
423 del_tree(path, TRUE);
425 file = g_dir_read_name(gdir);
443 ghb_vquality_range(signal_user_data_t *ud, gint *min, gint *max)
445 if (ghb_settings_get_bool(ud->settings, "directqp"))
447 gint vcodec = ghb_settings_get_int(ud->settings, "video_codec");
448 // Only x264 and ffmpeg currently support direct qp/crf entry
449 if (vcodec == HB_VCODEC_X264)
454 else if (vcodec == HB_VCODEC_FFMPEG)
472 static setting_value_t*
473 get_acodec_value(gint val)
475 setting_value_t *value = NULL;
478 for (ii = 0; ii < acodec_opts.count; ii++)
480 if (acodec_opts.map[ii].ivalue == val)
482 value = g_malloc(sizeof(setting_value_t));
483 value->option = g_strdup(acodec_opts.map[ii].option);
484 value->shortOpt = g_strdup(acodec_opts.map[ii].shortOpt);
485 value->svalue = g_strdup(acodec_opts.map[ii].svalue);
487 value->ivalue = acodec_opts.map[ii].ivalue;
488 value->dvalue = acodec_opts.map[ii].dvalue;
495 static setting_value_t*
496 get_amix_value(gint val)
498 setting_value_t *value = NULL;
501 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
503 if (hb_audio_mixdowns[ii].amixdown == val)
505 value = g_malloc(sizeof(setting_value_t));
506 value->option = g_strdup(hb_audio_mixdowns[ii].human_readable_name);
507 value->shortOpt = g_strdup(hb_audio_mixdowns[ii].short_name);
508 value->svalue = g_strdup(hb_audio_mixdowns[ii].internal_name);
510 value->ivalue = hb_audio_mixdowns[ii].amixdown;
511 value->dvalue = hb_audio_mixdowns[ii].amixdown;
518 // Handle for libhb. Gets set by ghb_backend_init()
519 static hb_handle_t * h = NULL;
521 extern void hb_get_tempory_directory(hb_handle_t *h, char path[512]);
524 ghb_hb_cleanup(gboolean partial)
528 hb_get_tempory_directory(h, dir);
529 del_tree(dir, !partial);
532 static hb_audio_config_t*
533 get_hb_audio(gint titleindex, gint track)
537 hb_audio_config_t *audio = NULL;
539 if (h == NULL) return NULL;
540 list = hb_get_titles( h );
541 if( !hb_list_count( list ) )
543 /* No valid title, stop right there */
546 title = hb_list_item( list, titleindex );
547 if (title == NULL) return NULL; // Bad titleindex
548 if (!hb_list_count(title->list_audio))
552 audio = (hb_audio_config_t *)hb_list_audio_config_item(title->list_audio, track);
557 search_rates(hb_rate_t *rates, gint rate, gint count)
560 for (ii = 0; ii < count; ii++)
562 if (rates[ii].rate == rate)
568 static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter);
571 get_combo_box_store(GtkBuilder *builder, const gchar *name)
576 g_debug("get_combo_box_store() %s\n", name);
577 // First modify the combobox model to allow greying out of options
578 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
579 store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
584 grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey)
589 store = get_combo_box_store(builder, name);
590 if (find_combo_item_by_int(GTK_TREE_MODEL(store), value, &iter))
592 gtk_list_store_set(store, &iter,
599 ghb_grey_combo_options(GtkBuilder *builder)
602 gint container, track, titleindex, acodec;
604 hb_audio_config_t *audio = NULL;
606 widget = GHB_WIDGET (builder, "title");
607 titleindex = ghb_widget_int(widget);
608 widget = GHB_WIDGET (builder, "audio_track");
609 track = ghb_widget_int(widget);
610 audio = get_hb_audio(titleindex, track);
611 widget = GHB_WIDGET (builder, "container");
612 container = ghb_widget_int(widget);
613 widget = GHB_WIDGET (builder, "http_optimize_mp4");
614 httpopt = ghb_widget_int(widget);
616 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, FALSE);
617 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, FALSE);
618 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, FALSE);
619 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_LAME, FALSE);
620 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_LAME, FALSE);
621 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_LAME, FALSE);
622 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, FALSE);
623 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, FALSE);
624 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, FALSE);
626 gboolean allow_ac3 = TRUE;
628 !(container == HB_MUX_MP4 && httpopt) &&
629 (container != HB_MUX_OGM);
633 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, FALSE);
634 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_AC3, FALSE);
635 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_AC3, FALSE);
639 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, TRUE);
640 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_AC3, TRUE);
641 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_AC3, TRUE);
643 if (audio && audio->in.codec != HB_ACODEC_AC3)
645 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, TRUE);
647 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, FALSE);
649 widget = GHB_WIDGET (builder, "audio_codec");
650 acodec = ghb_widget_int(widget);
651 if (acodec != HB_ACODEC_AC3)
653 grey_combo_box_item(builder, "audio_mix", 0, TRUE);
655 if (container == HB_MUX_MP4)
657 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_LAME, TRUE);
658 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_LAME, TRUE);
659 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_LAME, TRUE);
660 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, TRUE);
661 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, TRUE);
662 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, TRUE);
663 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, TRUE);
665 else if (container == HB_MUX_AVI)
667 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, TRUE);
668 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, TRUE);
669 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, TRUE);
670 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, TRUE);
671 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, TRUE);
672 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, TRUE);
673 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, TRUE);
675 else if (container == HB_MUX_OGM)
677 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, TRUE);
678 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, TRUE);
679 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, TRUE);
682 gboolean allow_mono = TRUE;
683 gboolean allow_stereo = TRUE;
684 gboolean allow_dolby = TRUE;
685 gboolean allow_dpl2 = TRUE;
686 gboolean allow_6ch = TRUE;
690 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
691 (acodec != HB_ACODEC_LAME);
692 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
694 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
696 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
697 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
698 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
699 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
701 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
702 (acodec != HB_ACODEC_LAME) &&
703 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
704 (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
706 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_MONO, !allow_mono);
707 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_STEREO, !allow_stereo);
708 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_DOLBY, !allow_dolby);
709 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
710 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_6CH, !allow_6ch);
714 ghb_get_best_mix(gint titleindex, gint track, gint acodec, gint mix)
716 hb_audio_config_t *audio = NULL;
717 gboolean allow_mono = TRUE;
718 gboolean allow_stereo = TRUE;
719 gboolean allow_dolby = TRUE;
720 gboolean allow_dpl2 = TRUE;
721 gboolean allow_6ch = TRUE;
723 if (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
725 // Audio codec pass-thru. No mixdown
728 audio = get_hb_audio(titleindex, track);
732 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
733 (acodec != HB_ACODEC_LAME);
734 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
736 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
738 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
739 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
740 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
741 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
743 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
744 (acodec != HB_ACODEC_LAME) &&
745 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
746 (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
748 gboolean greater = FALSE;
751 // If no mix is specified, select the best available.
752 mix = HB_AMIXDOWN_6CH;
754 if (mix == HB_AMIXDOWN_6CH)
757 if (allow_6ch) return HB_AMIXDOWN_6CH;
759 if (mix == HB_AMIXDOWN_DOLBYPLII || greater)
762 if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
764 if (mix == HB_AMIXDOWN_DOLBY || greater)
767 if (allow_dolby) return HB_AMIXDOWN_DOLBY;
769 if (mix == HB_AMIXDOWN_STEREO || greater)
772 if (allow_stereo) return HB_AMIXDOWN_STEREO;
774 if (mix == HB_AMIXDOWN_MONO || greater)
777 if (allow_mono) return HB_AMIXDOWN_MONO;
779 if (allow_stereo) return HB_AMIXDOWN_STEREO;
780 if (allow_dolby) return HB_AMIXDOWN_DOLBY;
781 if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
782 if (allow_6ch) return HB_AMIXDOWN_6CH;
786 // Set up the model for the combo box
788 init_combo_box(GtkBuilder *builder, const gchar *name)
792 GtkCellRenderer *cell;
794 g_debug("init_combo_box() %s\n", name);
795 // First modify the combobox model to allow greying out of options
796 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
798 // 1 - String to display
799 // 2 - bool indicating whether the entry is selectable (grey or not)
800 // 3 - String that is used for presets
801 // 4 - Int value determined by backend
802 // 5 - String value determined by backend
803 store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_BOOLEAN,
804 G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
805 gtk_combo_box_set_model(combo, GTK_TREE_MODEL(store));
807 gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo));
808 cell = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
809 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE);
810 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell,
811 "text", 0, "sensitive", 1, NULL);
815 audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
821 g_debug("audio_bitrate_opts_set ()\n");
822 store = get_combo_box_store(builder, name);
823 gtk_list_store_clear(store);
824 for (ii = 0; ii < count; ii++)
826 gtk_list_store_append(store, &iter);
827 gtk_list_store_set(store, &iter,
831 3, rates[ii].rate * 1000,
838 audio_bitrate_opts_clean(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
843 gboolean done = FALSE;
844 gboolean changed = FALSE;
846 g_debug("audio_bitrate_opts_clean ()\n");
847 store = get_combo_box_store(builder, name);
848 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter))
852 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1);
853 if (search_rates(rates, ivalue/1000, count) < 0)
855 done = !gtk_list_store_remove(store, &iter);
860 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
868 audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
874 g_debug("audio_samplerate_opts_set ()\n");
875 store = get_combo_box_store(builder, name);
876 gtk_list_store_clear(store);
877 // Add an item for "Same As Source"
878 gtk_list_store_append(store, &iter);
879 gtk_list_store_set(store, &iter,
886 for (ii = 0; ii < count; ii++)
888 gtk_list_store_append(store, &iter);
889 gtk_list_store_set(store, &iter,
900 video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
906 g_debug("video_rate_opts_set ()\n");
907 store = get_combo_box_store(builder, name);
908 gtk_list_store_clear(store);
909 // Add an item for "Same As Source"
910 gtk_list_store_append(store, &iter);
911 gtk_list_store_set(store, &iter,
918 for (ii = 0; ii < count; ii++)
922 if (strcmp(rates[ii].string, "23.976") == 0)
924 desc = "(NTSC Film)";
926 else if (strcmp(rates[ii].string, "25") == 0)
928 desc = "(PAL Film/Video)";
930 else if (strcmp(rates[ii].string, "29.97") == 0)
932 desc = "(NTSC Video)";
934 option = g_strdup_printf ("%s %s", rates[ii].string, desc);
935 gtk_list_store_append(store, &iter);
936 gtk_list_store_set(store, &iter,
948 mix_opts_set(GtkBuilder *builder, const gchar *name)
954 g_debug("audio_bitrate_opts_set ()\n");
955 store = get_combo_box_store(builder, name);
956 gtk_list_store_clear(store);
957 gtk_list_store_append(store, &iter);
958 gtk_list_store_set(store, &iter,
965 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
967 gtk_list_store_append(store, &iter);
968 gtk_list_store_set(store, &iter,
969 0, hb_audio_mixdowns[ii].human_readable_name,
971 2, hb_audio_mixdowns[ii].short_name,
972 3, hb_audio_mixdowns[ii].amixdown,
973 4, hb_audio_mixdowns[ii].internal_name,
979 language_opts_set(GtkBuilder *builder, const gchar *name)
985 g_debug("audio_bitrate_opts_set ()\n");
986 store = get_combo_box_store(builder, name);
987 gtk_list_store_clear(store);
988 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
990 gtk_list_store_append(store, &iter);
991 gtk_list_store_set(store, &iter,
992 0, language_table[ii].eng_name,
994 2, language_table[ii].iso639_2,
996 4, language_table[ii].iso639_1,
1002 title_opts_set(GtkBuilder *builder, const gchar *name)
1005 GtkListStore *store;
1011 g_debug("title_opts_set ()\n");
1012 store = get_combo_box_store(builder, name);
1013 gtk_list_store_clear(store);
1016 list = hb_get_titles( h );
1017 count = hb_list_count( list );
1018 if (count > 100) count = 100;
1022 // No titles. Fill in a default.
1023 gtk_list_store_append(store, &iter);
1024 gtk_list_store_set(store, &iter,
1033 for (ii = 0; ii < count; ii++)
1037 title = (hb_title_t*)hb_list_item(list, ii);
1038 if (title->duration != 0)
1040 option = g_strdup_printf ("%d - %02dh%02dm%02ds",
1041 title->index, title->hours, title->minutes, title->seconds);
1045 option = g_strdup_printf ("%d - Unknown Length", title->index);
1047 gtk_list_store_append(store, &iter);
1048 gtk_list_store_set(store, &iter,
1059 find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter)
1062 gboolean foundit = FALSE;
1064 if (gtk_tree_model_get_iter_first (store, iter))
1068 gtk_tree_model_get(store, iter, 3, &ivalue, -1);
1069 if (value == ivalue)
1074 } while (gtk_tree_model_iter_next (store, iter));
1080 audio_rate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
1083 GtkListStore *store;
1086 g_debug("audio_rate_opts_add ()\n");
1087 store = get_combo_box_store(builder, name);
1088 if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
1090 str = g_strdup_printf ("%.8g", (gdouble)rate/1000.0);
1091 gtk_list_store_append(store, &iter);
1092 gtk_list_store_set(store, &iter,
1105 audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1108 GtkListStore *store;
1111 hb_audio_config_t * audio;
1115 g_debug("audio_track_opts_set ()\n");
1116 store = get_combo_box_store(builder, name);
1117 gtk_list_store_clear(store);
1120 list = hb_get_titles( h );
1121 title = (hb_title_t*)hb_list_item( list, titleindex );
1124 count = hb_list_count( title->list_audio );
1127 if (count > 10) count = 10;
1130 // No audio. set some default
1131 gtk_list_store_append(store, &iter);
1132 gtk_list_store_set(store, &iter,
1141 for (ii = 0; ii < count; ii++)
1143 audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, ii );
1144 gtk_list_store_append(store, &iter);
1145 gtk_list_store_set(store, &iter,
1146 0, audio->lang.description,
1148 2, audio->lang.description,
1150 4, audio->lang.description,
1156 subtitle_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1159 GtkListStore *store;
1162 hb_subtitle_t * subtitle;
1166 g_debug("subtitle_opts_set ()\n");
1167 store = get_combo_box_store(builder, name);
1168 gtk_list_store_clear(store);
1171 list = hb_get_titles( h );
1172 title = (hb_title_t*)hb_list_item( list, titleindex );
1175 count = hb_list_count( title->list_subtitle );
1178 if (count > 10) count = 10;
1179 // Add options for "none" and "autoselect"
1180 gtk_list_store_append(store, &iter);
1181 gtk_list_store_set(store, &iter,
1188 gtk_list_store_append(store, &iter);
1189 gtk_list_store_set(store, &iter,
1196 for (ii = 0; ii < count; ii++)
1198 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, ii );
1199 gtk_list_store_append(store, &iter);
1200 gtk_list_store_set(store, &iter,
1203 2, subtitle->iso639_2,
1205 4, subtitle->iso639_2,
1208 if (titleindex == -1)
1210 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1212 gtk_list_store_append(store, &iter);
1213 gtk_list_store_set(store, &iter,
1214 0, language_table[ii].eng_name,
1216 2, language_table[ii].iso639_2,
1218 4, language_table[ii].iso639_2,
1231 guint64 longest = 0;
1232 gint titleindex = 0;
1234 g_debug("ghb_longest_title ()\n");
1235 if (h == NULL) return 0;
1236 list = hb_get_titles( h );
1237 count = hb_list_count( list );
1238 if (count > 100) count = 100;
1239 for (ii = 0; ii < count; ii++)
1241 title = (hb_title_t*)hb_list_item(list, ii);
1242 if (title->duration > longest)
1245 longest = title->duration;
1252 ghb_find_audio_track(gint titleindex, const gchar *lang, gint acodec)
1256 hb_audio_config_t * audio;
1261 g_debug("find_audio_track ()\n");
1264 list = hb_get_titles( h );
1265 title = (hb_title_t*)hb_list_item( list, titleindex );
1268 count = hb_list_count( title->list_audio );
1271 if (count > 10) count = 10;
1272 for (ii = 0; ii < count; ii++)
1274 audio = (hb_audio_config_t*)hb_list_audio_config_item( title->list_audio, ii );
1275 if ((strcmp(lang, audio->lang.iso639_2) == 0) ||
1276 (strcmp(lang, "und") == 0))
1278 // Candidate track. Will use if no better match found
1280 if (audio->in.codec == acodec)
1291 generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
1294 GtkListStore *store;
1297 g_debug("generic_opts_set ()\n");
1298 store = get_combo_box_store(builder, name);
1299 gtk_list_store_clear(store);
1300 for (ii = 0; ii < opts->count; ii++)
1302 gtk_list_store_append(store, &iter);
1303 gtk_list_store_set(store, &iter,
1304 0, opts->map[ii].option,
1306 2, opts->map[ii].shortOpt,
1307 3, opts->map[ii].ivalue,
1308 4, opts->map[ii].svalue,
1314 ghb_update_ui_combo_box(GtkBuilder *builder, const gchar *name, gint user_data, gboolean all)
1316 GtkComboBox *combo = NULL;
1318 gint handler_id = 0;
1320 g_debug("ghb_update_ui_combo_box() %s\n", name);
1323 // Clearing a combo box causes a rash of "changed" events, even when
1324 // the active item is -1 (inactive). To control things, I'm disabling
1325 // the event till things are settled down.
1326 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1327 signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX);
1330 // Valid signal id found. This should always succeed.
1331 handler_id = g_signal_handler_find ((gpointer)combo, G_SIGNAL_MATCH_ID,
1332 signal_id, 0, 0, 0, 0);
1335 // This should also always succeed
1336 g_signal_handler_block ((gpointer)combo, handler_id);
1340 if (all || strcmp(name, "audio_bitrate") == 0)
1341 audio_bitrate_opts_set(builder, "audio_bitrate", hb_audio_bitrates, hb_audio_bitrates_count);
1342 if (all || strcmp(name, "pref_audio_bitrate1") == 0)
1343 audio_bitrate_opts_set(builder, "pref_audio_bitrate1", hb_audio_bitrates, hb_audio_bitrates_count);
1344 if (all || strcmp(name, "pref_audio_bitrate2") == 0)
1345 audio_bitrate_opts_set(builder, "pref_audio_bitrate2", hb_audio_bitrates, hb_audio_bitrates_count);
1346 if (all || strcmp(name, "audio_sample_rate") == 0)
1347 audio_samplerate_opts_set(builder, "audio_sample_rate", hb_audio_rates, hb_audio_rates_count);
1348 if (all || strcmp(name, "pref_audio_rate1") == 0)
1349 audio_samplerate_opts_set(builder, "pref_audio_rate1", hb_audio_rates, hb_audio_rates_count);
1350 if (all || strcmp(name, "pref_audio_rate2") == 0)
1351 audio_samplerate_opts_set(builder, "pref_audio_rate2", hb_audio_rates, hb_audio_rates_count);
1352 if (all || strcmp(name, "framerate") == 0)
1353 video_rate_opts_set(builder, "framerate", hb_video_rates, hb_video_rates_count);
1354 if (all || strcmp(name, "audio_mix") == 0)
1355 mix_opts_set(builder, "audio_mix");
1356 if (all || strcmp(name, "pref_audio_mix1") == 0)
1357 mix_opts_set(builder, "pref_audio_mix1");
1358 if (all || strcmp(name, "pref_audio_mix2") == 0)
1359 mix_opts_set(builder, "pref_audio_mix2");
1360 if (all || strcmp(name, "pref_source_audio_lang") == 0)
1361 language_opts_set(builder, "pref_source_audio_lang");
1362 if (all || strcmp(name, "subtitle_lang") == 0)
1363 subtitle_opts_set(builder, "subtitle_lang", user_data);
1364 if (all || strcmp(name, "title") == 0)
1365 title_opts_set(builder, "title");
1366 if (all || strcmp(name, "audio_track") == 0)
1367 audio_track_opts_set(builder, "audio_track", user_data);
1368 if (all || strcmp(name, "container") == 0)
1369 generic_opts_set(builder, "container", &container_opts);
1370 if (all || strcmp(name, "deinterlace") == 0)
1371 generic_opts_set(builder, "deinterlace", &deint_opts);
1372 if (all || strcmp(name, "denoise") == 0)
1373 generic_opts_set(builder, "denoise", &denoise_opts);
1374 if (all || strcmp(name, "video_codec") == 0)
1375 generic_opts_set(builder, "video_codec", &vcodec_opts);
1376 if (all || strcmp(name, "audio_codec") == 0)
1377 generic_opts_set(builder, "audio_codec", &acodec_opts);
1378 if (all || strcmp(name, "pref_audio_codec1") == 0)
1379 generic_opts_set(builder, "pref_audio_codec1", &pref_acodec_opts);
1380 if (all || strcmp(name, "pref_audio_codec2") == 0)
1381 generic_opts_set(builder, "pref_audio_codec2", &pref_acodec_opts);
1382 if (all || strcmp(name, "pref_source_audio_codec") == 0)
1383 generic_opts_set(builder, "pref_source_audio_codec", &source_acodec_opts);
1384 if (all || strcmp(name, "x264_direct") == 0)
1385 generic_opts_set(builder, "x264_direct", &direct_opts);
1386 if (all || strcmp(name, "x264_me") == 0)
1387 generic_opts_set(builder, "x264_me", &me_opts);
1388 if (all || strcmp(name, "x264_subme") == 0)
1389 generic_opts_set(builder, "x264_subme", &subme_opts);
1390 if (all || strcmp(name, "x264_analyse") == 0)
1391 generic_opts_set(builder, "x264_analyse", &analyse_opts);
1392 if (all || strcmp(name, "x264_trellis") == 0)
1393 generic_opts_set(builder, "x264_trellis", &trellis_opts);
1396 g_signal_handler_unblock ((gpointer)combo, handler_id);
1401 init_ui_combo_boxes(GtkBuilder *builder)
1403 init_combo_box(builder, "audio_bitrate");
1404 init_combo_box(builder, "pref_audio_bitrate1");
1405 init_combo_box(builder, "pref_audio_bitrate2");
1406 init_combo_box(builder, "audio_sample_rate");
1407 init_combo_box(builder, "pref_audio_rate1");
1408 init_combo_box(builder, "pref_audio_rate2");
1409 init_combo_box(builder, "framerate");
1410 init_combo_box(builder, "audio_mix");
1411 init_combo_box(builder, "pref_audio_mix1");
1412 init_combo_box(builder, "pref_audio_mix2");
1413 init_combo_box(builder, "pref_source_audio_lang");
1414 init_combo_box(builder, "subtitle_lang");
1415 init_combo_box(builder, "title");
1416 init_combo_box(builder, "audio_track");
1417 init_combo_box(builder, "container");
1418 init_combo_box(builder, "deinterlace");
1419 init_combo_box(builder, "denoise");
1420 init_combo_box(builder, "video_codec");
1421 init_combo_box(builder, "audio_codec");
1422 init_combo_box(builder, "pref_audio_codec1");
1423 init_combo_box(builder, "pref_audio_codec2");
1424 init_combo_box(builder, "pref_source_audio_codec");
1425 init_combo_box(builder, "x264_direct");
1426 init_combo_box(builder, "x264_me");
1427 init_combo_box(builder, "x264_subme");
1428 init_combo_box(builder, "x264_analyse");
1429 init_combo_box(builder, "x264_trellis");
1432 static const char * turbo_opts =
1433 "ref=1:subme=1:me=dia:analyse=none:trellis=0:"
1434 "no-fast-pskip=0:8x8dct=0:weightb=0";
1436 // Construct the x264 options string
1437 // The result is allocated, so someone must free it at some point.
1439 ghb_build_x264opts_string(GHashTable *settings)
1441 GString *x264opts = g_string_new("");
1442 gint refs = ghb_settings_get_int(settings, "x264_refs");
1445 g_string_append_printf(x264opts, "ref=%d:", refs);
1449 if (ghb_settings_get_bool(settings, "x264_mixed_refs"))
1451 g_string_append(x264opts, "mixed-refs=1:");
1454 gint subme = ghb_settings_get_int(settings, "x264_subme");
1455 if (subme != 5) // 5 is default
1457 g_string_append_printf(x264opts, "subme=%d:", subme);
1459 gint bframes = ghb_settings_get_int(settings, "x264_bframes");
1462 g_string_append_printf(x264opts, "bframes=%d:", bframes);
1463 if (ghb_settings_get_bool(settings, "x264_weighted_bframes"))
1465 g_string_append(x264opts, "weightb=1:");
1469 if (ghb_settings_get_bool(settings, "x264_brdo"))
1471 g_string_append(x264opts, "brdo=1:");
1474 if (ghb_settings_get_bool(settings, "x264_bime"))
1476 g_string_append(x264opts, "bime=1:");
1481 if (ghb_settings_get_bool(settings, "x264_bpyramid"))
1483 g_string_append(x264opts, "b-pyramid=1:");
1486 if (ghb_settings_get_bool(settings, "x264_no_fast_pskip"))
1488 g_string_append(x264opts, "no-fast-pskip=1:");
1490 if (ghb_settings_get_bool(settings, "x264_no_dct_decimate"))
1492 g_string_append(x264opts, "no-dct-decimate=1:");
1494 if (!ghb_settings_get_bool(settings, "x264_cabac"))
1496 g_string_append(x264opts, "cabac=0:");
1500 gint trellis = ghb_settings_get_int(settings, "x264_trellis");
1501 if (trellis != 0); // != None
1503 g_string_append_printf(x264opts, "trellis=%d:", trellis);
1507 dba = ghb_settings_get_int(settings, "x264_deblock_alpha");
1508 dbb = ghb_settings_get_int(settings, "x264_deblock_beta");
1509 if (dba != 0 || dbb != 0)
1511 g_string_append_printf(x264opts, "deblock=%d,%d:", dba, dbb);
1513 const gchar *me = ghb_settings_get_string(settings, "x264_me");
1514 g_string_append_printf(x264opts, "me=%s:", me);
1515 gint analyse = ghb_settings_get_int(settings, "x264_analyse");
1516 if (analyse != 0) // != Some
1518 g_string_append_printf(x264opts, "analyse=%s:",
1519 ghb_settings_get_string(settings, "x264_analyse"));
1521 if (analyse != 1) // != none
1523 gint direct = ghb_settings_get_int(settings, "x264_direct");
1524 if (direct != 1) // !spatial
1526 g_string_append_printf(x264opts, "direct=%s:",
1527 ghb_settings_get_string(settings, "x264_direct"));
1530 g_string_append_printf(x264opts, "merange=%d:",
1531 ghb_settings_get_int(settings, "x264_merange"));
1533 const gchar *opts = ghb_settings_get_string(settings, "x264_options");
1534 if (opts != NULL && opts[0] != 0)
1536 g_string_append_printf(x264opts, "%s:", opts);
1538 // strip the trailing ":"
1541 result = g_string_free(x264opts, FALSE);
1542 len = strlen(result);
1543 if (len > 0) result[len - 1] = 0;
1548 ghb_get_chapters(gint titleindex)
1552 hb_chapter_t * chapter;
1554 gchar **result = NULL;
1556 g_debug("ghb_get_chapters (title = %d)\n", titleindex);
1557 if (h == NULL) return NULL;
1558 list = hb_get_titles( h );
1559 title = (hb_title_t*)hb_list_item( list, titleindex );
1560 if (title == NULL) return NULL;
1561 count = hb_list_count( title->list_chapter );
1562 result = g_malloc((count+1) * sizeof(gchar*));
1563 for (ii = 0; ii < count; ii++)
1565 chapter = hb_list_item(title->list_chapter, ii);
1566 if (chapter == NULL) break;
1567 if (chapter->title == NULL || chapter->title[0] == 0)
1568 result[ii] = g_strdup_printf ("Chapter %2d", ii);
1570 result[ii] = g_strdup(chapter->title);
1577 ghb_ac3_in_audio_list(GSList *audio_list)
1582 while (link != NULL)
1584 GHashTable *asettings;
1587 asettings = (GHashTable*)link->data;
1588 acodec = ghb_settings_get_int(asettings, "audio_codec");
1589 if (acodec == HB_ACODEC_AC3)
1597 ghb_set_passthru_rate_opts(GtkBuilder *builder, gint bitrate)
1599 gboolean changed = FALSE;
1600 changed = audio_rate_opts_add(builder, "audio_bitrate", bitrate);
1605 ghb_set_default_rate_opts(GtkBuilder *builder)
1607 gboolean changed = FALSE;
1608 changed = audio_bitrate_opts_clean(builder, "audio_bitrate", hb_audio_bitrates, hb_audio_bitrates_count);
1612 static ghb_status_t hb_status;
1615 ghb_backend_init(GtkBuilder *builder, gint debug, gint update)
1618 h = hb_init( debug, update );
1619 // Set up the list model for the combos
1620 init_ui_combo_boxes(builder);
1621 // Populate all the combos
1622 ghb_update_ui_combo_box(builder, NULL, 0, TRUE);
1626 ghb_backend_scan(const gchar *path, gint titleindex)
1628 hb_scan( h, path, titleindex );
1629 hb_status.state |= GHB_STATE_SCANNING;
1630 // initialize count and cur to something that won't cause FPE
1631 // when computing progress
1632 hb_status.title_count = 1;
1633 hb_status.title_cur = 0;
1639 return hb_status.state;
1643 ghb_clear_state(gint state)
1645 hb_status.state &= ~state;
1649 ghb_set_state(gint state)
1651 hb_status.state |= state;
1655 ghb_get_status(ghb_status_t *status)
1657 memcpy(status, &hb_status, sizeof(ghb_status_t));
1664 static gint scan_complete_count = 0;
1667 if (h == NULL) return;
1668 hb_get_state( h, &s );
1669 scans = hb_get_scancount(h);
1670 if (scans > scan_complete_count)
1672 hb_status.state &= ~GHB_STATE_SCANNING;
1673 hb_status.state |= GHB_STATE_SCANDONE;
1674 scan_complete_count = hb_get_scancount(h);
1682 #define p s.param.scanning
1683 case HB_STATE_SCANNING:
1685 hb_status.state |= GHB_STATE_SCANNING;
1686 hb_status.title_count = p.title_count;
1687 hb_status.title_cur = p.title_cur;
1691 case HB_STATE_SCANDONE:
1693 hb_status.state &= ~GHB_STATE_SCANNING;
1694 hb_status.state |= GHB_STATE_SCANDONE;
1697 #define p s.param.working
1698 case HB_STATE_WORKING:
1699 hb_status.state |= GHB_STATE_WORKING;
1700 hb_status.state &= ~GHB_STATE_PAUSED;
1701 hb_status.job_cur = p.job_cur;
1702 hb_status.job_count = p.job_count;
1703 hb_status.progress = p.progress;
1704 hb_status.rate_cur = p.rate_cur;
1705 hb_status.rate_avg = p.rate_avg;
1706 hb_status.hours = p.hours;
1707 hb_status.minutes = p.minutes;
1708 hb_status.seconds = p.seconds;
1709 hb_status.unique_id = p.sequence_id & 0xFFFFFF;
1713 case HB_STATE_PAUSED:
1714 hb_status.state |= GHB_STATE_PAUSED;
1717 #define p s.param.muxing
1718 case HB_STATE_MUXING:
1720 hb_status.state |= GHB_STATE_MUXING;
1724 #define p s.param.workdone
1725 case HB_STATE_WORKDONE:
1729 hb_status.state |= GHB_STATE_WORKDONE;
1730 hb_status.state &= ~GHB_STATE_MUXING;
1731 hb_status.state &= ~GHB_STATE_PAUSED;
1732 hb_status.state &= ~GHB_STATE_WORKING;
1736 hb_status.error = GHB_ERROR_NONE;
1737 case HB_ERROR_CANCELED:
1738 hb_status.error = GHB_ERROR_CANCELED;
1740 hb_status.error = GHB_ERROR_FAIL;
1742 hb_status.error = p.error;
1743 // Delete all remaining jobs of this encode.
1744 // An encode can be composed of multiple associated jobs.
1745 // When a job is stopped, libhb removes it from the job list,
1746 // but does not remove other jobs that may be associated with it.
1747 // Associated jobs are taged in the sequence id.
1748 while (((job = hb_job(h, 0)) != NULL) && ((job->sequence_id >> 24) != 0) )
1756 ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
1761 if (h == NULL) return FALSE;
1762 list = hb_get_titles( h );
1763 if( !hb_list_count( list ) )
1765 /* No valid title, stop right there */
1769 title = hb_list_item( list, titleindex );
1770 if (title == NULL) return FALSE; // Bad titleindex
1771 tinfo->width = title->width;
1772 tinfo->height = title->height;
1773 memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
1774 // Don't allow crop to 0
1775 if (title->crop[0] + title->crop[1] >= title->height)
1776 title->crop[0] = title->crop[1] = 0;
1777 if (title->crop[2] + title->crop[3] >= title->width)
1778 title->crop[2] = title->crop[3] = 0;
1779 tinfo->num_chapters = hb_list_count(title->list_chapter);
1780 tinfo->rate_base = title->rate_base;
1781 tinfo->rate = title->rate;
1782 hb_reduce(&(tinfo->aspect_n), &(tinfo->aspect_d),
1783 title->width * title->pixel_aspect_width,
1784 title->height * title->pixel_aspect_height);
1785 tinfo->hours = title->hours;
1786 tinfo->minutes = title->minutes;
1787 tinfo->seconds = title->seconds;
1788 tinfo->duration = title->duration;
1789 g_message("duration %ld", title->duration);
1794 ghb_get_audio_info(ghb_audio_info_t *ainfo, gint titleindex, gint audioindex)
1796 hb_audio_config_t *audio;
1798 audio = get_hb_audio(titleindex, audioindex);
1799 if (audio == NULL) return FALSE; // Bad audioindex
1800 ainfo->codec = audio->in.codec;
1801 ainfo->bitrate = audio->in.bitrate;
1802 ainfo->samplerate = audio->in.samplerate;
1807 ghb_audio_is_passthru(gint acodec)
1809 g_debug("ghb_audio_is_passthru () \n");
1810 g_debug("acodec %d\n", acodec);
1811 return (acodec == HB_ACODEC_AC3);
1815 ghb_get_default_acodec()
1817 return HB_ACODEC_FAAC;
1821 ghb_set_scale(signal_user_data_t *ud, gint mode)
1826 GHashTable *settings = ud->settings;
1827 gboolean keep_aspect, round_dims, anamorphic;
1828 gboolean autocrop, autoscale, noscale;
1829 gint crop[4], width, height, par_width, par_height;
1830 gint crop_width, crop_height;
1831 gint aspect_n, aspect_d;
1832 gboolean keep_width = (mode == GHB_SCALE_KEEP_WIDTH);
1833 gboolean keep_height = (mode == GHB_SCALE_KEEP_HEIGHT);
1839 gint max_height = 0;
1841 g_debug("ghb_set_scale ()\n");
1843 if (h == NULL) return;
1844 list = hb_get_titles( h );
1845 if( !hb_list_count( list ) )
1847 /* No valid title, stop right there */
1850 gint titleindex = ghb_settings_get_index(settings, "title");
1851 title = hb_list_item( list, titleindex );
1852 if (title == NULL) return;
1854 if (job == NULL) return;
1856 // First configure widgets
1857 round_dims = ghb_settings_get_bool(ud->settings, "round_dimensions");
1858 anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
1859 keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
1860 autocrop = ghb_settings_get_bool(ud->settings, "autocrop");
1861 autoscale = ghb_settings_get_bool(ud->settings, "autoscale");
1862 // "Noscale" is a flag that says we prefer to crop extra to satisfy
1863 // alignment constraints rather than scaling to satisfy them.
1864 noscale = ghb_settings_get_bool(ud->settings, "noscale");
1865 // Align dimensions to either 16 or 2 pixels
1866 // The scaler crashes if the dimensions are not divisible by 2
1867 // x264 also will not accept dims that are not multiple of 2
1868 modshift = round_dims ? 4 : 1;
1869 modround = round_dims ? 8 : 1;
1873 keep_height = FALSE;
1875 if (anamorphic || keep_aspect)
1877 keep_height = FALSE;
1879 // Step needs to be at least 2 because odd widths cause scaler crash
1880 step = round_dims ? 16 : 2;
1881 widget = GHB_WIDGET (ud->builder, "scale_width");
1882 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
1883 widget = GHB_WIDGET (ud->builder, "scale_height");
1884 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
1887 ghb_title_info_t tinfo;
1889 if (ghb_get_title_info (&tinfo, titleindex))
1891 crop[0] = tinfo.crop[0];
1892 crop[1] = tinfo.crop[1];
1893 crop[2] = tinfo.crop[2];
1894 crop[3] = tinfo.crop[3];
1899 // Adjust the cropping to accomplish the desired width and height
1900 crop_width = tinfo.width - crop[2] - crop[3];
1901 crop_height = tinfo.height - crop[0] - crop[1];
1902 width = (crop_width >> modshift) << modshift;
1903 height = (crop_height >> modshift) << modshift;
1904 need1 = (crop_height - height) / 2;
1905 need2 = crop_height - height - need1;
1908 need1 = (crop_width - width) / 2;
1909 need2 = crop_width - width - need1;
1913 ghb_ui_update_int (ud, "crop_top", crop[0]);
1914 ghb_ui_update_int (ud, "crop_bottom", crop[1]);
1915 ghb_ui_update_int (ud, "crop_left", crop[2]);
1916 ghb_ui_update_int (ud, "crop_right", crop[3]);
1919 crop[0] = ghb_settings_get_int(ud->settings, "crop_top");
1920 crop[1] = ghb_settings_get_int(ud->settings, "crop_bottom");
1921 crop[2] = ghb_settings_get_int(ud->settings, "crop_left");
1922 crop[3] = ghb_settings_get_int(ud->settings, "crop_right");
1923 hb_reduce(&aspect_n, &aspect_d,
1924 title->width * title->pixel_aspect_width,
1925 title->height * title->pixel_aspect_height);
1926 crop_width = title->width - crop[2] - crop[3];
1927 crop_height = title->height - crop[0] - crop[1];
1931 height = crop_height;
1932 max_width = crop_width;
1933 max_height = crop_height;
1937 width = ghb_settings_get_int(ud->settings, "scale_width");
1938 height = ghb_settings_get_int(ud->settings, "scale_height");
1939 max_width = ghb_settings_get_int(ud->settings, "max_width");
1940 max_height = ghb_settings_get_int(ud->settings, "max_width");
1942 max_width = (max_width >> modshift) << modshift;
1943 max_height = (max_height >> modshift) << modshift;
1944 // Adjust dims according to max values
1947 max_height = crop_height;
1951 max_width = crop_width;
1953 height = MIN(height, max_height);
1954 width = MIN(width, max_width);
1955 g_debug("max_width %d, max_height %d\n", max_width, max_height);
1958 width = title->width - crop[2] - crop[3];
1960 height = title->height - crop[0] - crop[1];
1970 // The scaler crashes if the dimensions are not divisible by 2
1971 // Align mod 2. And so does something in x264_encoder_headers()
1976 job->maxHeight = max_height;
1977 job->crop[0] = crop[0]; job->crop[1] = crop[1];
1978 job->crop[2] = crop[2]; job->crop[3] = crop[3];
1979 hb_set_anamorphic_size( job, &width, &height, &par_width, &par_height );
1986 gint new_width, new_height;
1988 g_debug("kw %s kh %s\n", keep_width ? "y":"n", keep_height ? "y":"n");
1989 g_debug("w %d h %d\n", width, height);
1990 // Compute pixel aspect ration.
1991 par = (gdouble)(title->height * aspect_n) / (title->width * aspect_d);
1992 // Must scale so that par becomes 1:1
1993 // Try to keep largest dimension
1994 new_height = (crop_height * ((gdouble)width/crop_width) / par);
1995 new_width = (crop_width * ((gdouble)height/crop_height) * par);
1996 // Height and width are always multiples of 2, so do the rounding
1997 new_height = ((new_height + 1) >> 1) << 1;
1998 new_width = ((new_width + 1) >> 1) << 1;
1999 g_debug("max w %d, new w %d\n", max_width, new_width);
2000 if (max_width && (new_width > max_width))
2002 height = new_height;
2004 else if (max_height && (new_height > max_height))
2008 else if (keep_width)
2010 height = new_height;
2012 else if (keep_height)
2016 else if (width > new_width)
2018 height = new_height;
2024 g_debug("new w %d h %d\n", width, height);
2026 width = ((width + modround) >> modshift) << modshift;
2027 height = ((height + modround) >> modshift) << modshift;
2029 ghb_ui_update_int (ud, "scale_width", width);
2030 ghb_ui_update_int (ud, "scale_height", height);
2034 set_preview_job_settings(hb_job_t *job, GHashTable *settings)
2036 job->crop[0] = ghb_settings_get_int(settings, "crop_top");
2037 job->crop[1] = ghb_settings_get_int(settings, "crop_bottom");
2038 job->crop[2] = ghb_settings_get_int(settings, "crop_left");
2039 job->crop[3] = ghb_settings_get_int(settings, "crop_right");
2041 gboolean anamorphic = ghb_settings_get_bool(settings, "anamorphic");
2042 gboolean round_dimensions = ghb_settings_get_bool(settings, "round_dimensions");
2043 if (round_dimensions && anamorphic)
2046 job->pixel_ratio = 2;
2048 else if (anamorphic)
2051 job->pixel_ratio = 2;
2056 job->pixel_ratio = 0;
2058 job->width = ghb_settings_get_int(settings, "scale_width");
2059 job->height = ghb_settings_get_int(settings, "scale_height");
2060 gint deint = ghb_settings_get_int(settings, "deinterlace");
2061 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2062 job->deinterlace = (!decomb && deint == 0) ? 0 : 1;
2066 ghb_calculate_target_bitrate(GHashTable *settings, gint titleindex)
2073 if (h == NULL) return 2000;
2074 list = hb_get_titles( h );
2075 title = hb_list_item( list, titleindex );
2076 if (title == NULL) return 2000;
2078 if (job == NULL) return 2000;
2079 size = ghb_settings_get_int(settings, "video_target_size");
2080 return hb_calc_bitrate( job, size );
2084 ghb_guess_bitrate(GHashTable *settings)
2087 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2089 // This is really rough. I'm trying to err on the high
2090 // side since this is used to estimate if there is
2091 // sufficient disk space left
2092 gint vcodec = ghb_settings_get_int(settings, "video_codec");
2093 gdouble vquality = ghb_settings_get_dbl(settings, "video_quality")/100;
2094 if (vcodec == HB_VCODEC_X264 &&
2095 !ghb_settings_get_bool(settings, "linear_vquality"))
2097 vquality = 51.0 - vquality * 51.0;
2098 // Convert log curve to linear
2099 vquality = exp2((vquality-12)/6);
2100 // Don't let it go to 0
2101 if (vquality >= 31) vquality = 30;
2102 vquality = (31 - vquality) / 31;
2104 // bitrate seems to be a log relasionship to quality
2105 // with typical source material
2106 // This is a real wag
2107 bitrate = 20*1024*1024*exp10(vquality*14)/exp10(14);
2108 // Add some bits for audio
2109 bitrate += 500*1024;
2113 // Add some fudge to the bitrate to leave breathing room
2114 bitrate = ghb_settings_get_int(settings, "video_bitrate")*1024;
2115 // Add some bits for audio
2116 bitrate += 500*1024;
2122 ghb_validate_video(signal_user_data_t *ud)
2124 GHashTable *settings = ud->settings;
2128 mux = ghb_settings_get_int(settings, "container");
2129 vcodec = ghb_settings_get_int(settings, "video_codec");
2130 if ((mux == HB_MUX_MP4 || mux == HB_MUX_AVI) &&
2131 (vcodec == HB_VCODEC_THEORA))
2133 // mp4|avi/theora combination is not supported.
2134 message = g_strdup_printf(
2135 "Theora is not supported in the MP4 and AVI containers.\n\n"
2136 "You should choose a different video codec or container.\n"
2137 "If you continue, XviD will be chosen for you.");
2138 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2144 vcodec = HB_VCODEC_XVID;
2145 ghb_ui_update_int(ud, "video_codec", vcodec);
2147 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2148 gboolean vfr = ghb_settings_get_bool(settings, "variable_frame_rate");
2151 message = g_strdup_printf(
2152 "Decomb is intended to be used in conjunction\n"
2153 "with variable frame rate.\n\n"
2154 "Would you like me to enable VFR for you?");
2155 if (ghb_message_dialog(GTK_MESSAGE_WARNING, message, "No", "Yes"))
2157 ghb_ui_update_int(ud, "variable_frame_rate", TRUE);
2165 ghb_validate_container(signal_user_data_t *ud)
2170 container = ghb_settings_get_bool(ud->settings, "container");
2171 if (container == HB_MUX_MP4)
2174 httpopt = ghb_settings_get_bool(ud->settings, "http_optimize_mp4");
2175 if (httpopt && ghb_ac3_in_audio_list(ud->audio_settings))
2177 message = g_strdup_printf(
2178 "AC3 audio in HTTP optimized MP4 is not supported.\n\n"
2179 "You should choose a different audio codec.\n"
2180 "If you continue, FAAC will be chosen for you.");
2181 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2187 GSList *link = ud->audio_settings;
2188 while (link != NULL)
2190 GHashTable *asettings;
2191 asettings = (GHashTable*)link->data;
2192 gint acodec = ghb_settings_get_int(asettings, "audio_codec");
2193 if (acodec == HB_ACODEC_AC3)
2195 setting_value_t *value;
2196 value = get_acodec_value(HB_ACODEC_FAAC);
2197 ghb_settings_set(asettings, "audio_codec", value);
2207 ghb_validate_audio(signal_user_data_t *ud)
2211 GHashTable *settings = ud->settings;
2213 setting_value_t *value;
2215 if (h == NULL) return FALSE;
2216 list = hb_get_titles( h );
2217 if( !hb_list_count( list ) )
2219 /* No valid title, stop right there */
2220 g_message("No title found.\n");
2224 gint titleindex = ghb_settings_get_index(settings, "title");
2225 title = hb_list_item( list, titleindex );
2226 if (title == NULL) return FALSE;
2227 GSList *link = ud->audio_settings;
2228 gint mux = ghb_settings_get_int(settings, "container");
2229 while (link != NULL)
2231 GHashTable *asettings;
2232 hb_audio_config_t *taudio;
2234 asettings = (GHashTable*)link->data;
2235 gint track = ghb_settings_get_index(asettings, "audio_track");
2236 gint codec = ghb_settings_get_int(asettings, "audio_codec");
2237 taudio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, track );
2238 if ((taudio->in.codec != HB_ACODEC_AC3) && (codec == HB_ACODEC_AC3))
2240 // Not supported. AC3 is passthrough only, so input must be AC3
2241 message = g_strdup_printf(
2242 "The source does not support AC3 Pass-Thru.\n\n"
2243 "You should choose a different audio codec.\n"
2244 "If you continue, one will be chosen for you.");
2245 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2251 if (mux == HB_MUX_AVI)
2253 codec = HB_ACODEC_LAME;
2257 codec = HB_ACODEC_FAAC;
2259 value = get_acodec_value(codec);
2260 ghb_settings_set(asettings, "audio_codec", value);
2262 gchar *a_unsup = NULL;
2263 gchar *mux_s = NULL;
2264 if (mux == HB_MUX_MP4)
2267 // mp4/mp3|vorbis combination is not supported.
2268 if (codec == HB_ACODEC_LAME)
2271 codec = HB_ACODEC_FAAC;
2273 if (codec == HB_ACODEC_VORBIS)
2276 codec = HB_ACODEC_FAAC;
2279 else if (mux == HB_MUX_AVI)
2282 // avi/faac|vorbis combination is not supported.
2283 if (codec == HB_ACODEC_FAAC)
2286 codec = HB_ACODEC_LAME;
2288 if (codec == HB_ACODEC_VORBIS)
2291 codec = HB_ACODEC_LAME;
2294 else if (mux == HB_MUX_OGM)
2297 // avi/faac|vorbis combination is not supported.
2298 if (codec == HB_ACODEC_FAAC)
2301 codec = HB_ACODEC_VORBIS;
2303 if (codec == HB_ACODEC_AC3)
2306 codec = HB_ACODEC_VORBIS;
2311 message = g_strdup_printf(
2312 "%s is not supported in the %s container.\n\n"
2313 "You should choose a different audio codec.\n"
2314 "If you continue, one will be chosen for you.", a_unsup, mux_s);
2315 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2321 value = get_acodec_value(codec);
2322 ghb_settings_set(asettings, "audio_codec", value);
2324 gint mix = ghb_settings_get_int (asettings, "audio_mix");
2325 gboolean allow_mono = TRUE;
2326 gboolean allow_stereo = TRUE;
2327 gboolean allow_dolby = TRUE;
2328 gboolean allow_dpl2 = TRUE;
2329 gboolean allow_6ch = TRUE;
2331 (taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
2332 (codec != HB_ACODEC_LAME);
2333 gint layout = taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
2335 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
2337 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
2338 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
2339 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
2340 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
2342 (taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
2343 (codec != HB_ACODEC_LAME) &&
2344 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
2345 (taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
2347 gchar *mix_unsup = NULL;
2348 if (mix == HB_AMIXDOWN_MONO && !allow_mono)
2352 if (mix == HB_AMIXDOWN_STEREO && !allow_stereo)
2354 mix_unsup = "stereo";
2356 if (mix == HB_AMIXDOWN_DOLBY && !allow_dolby)
2358 mix_unsup = "Dolby";
2360 if (mix == HB_AMIXDOWN_DOLBYPLII && !allow_dpl2)
2362 mix_unsup = "Dolby Pro Logic II";
2364 if (mix == HB_AMIXDOWN_6CH && !allow_6ch)
2366 mix_unsup = "6 Channel";
2370 message = g_strdup_printf(
2371 "The source audio does not support %s mixdown.\n\n"
2372 "You should choose a different mixdown.\n"
2373 "If you continue, one will be chosen for you.", mix_unsup);
2374 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2380 mix = ghb_get_best_mix(titleindex, track, codec, mix);
2381 value = get_amix_value(mix);
2382 ghb_settings_set(asettings, "audio_mix", value);
2390 ghb_validate_vquality(GHashTable *settings)
2396 if (ghb_settings_get_bool(settings, "nocheckvquality")) return TRUE;
2397 vcodec = ghb_settings_get_int(settings, "video_codec");
2398 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2400 if (!ghb_settings_get_bool(settings, "directqp"))
2402 if (vcodec != HB_VCODEC_X264 ||
2403 ghb_settings_get_bool(settings, "linear_vquality"))
2408 else if (vcodec == HB_VCODEC_X264)
2416 if (vcodec == HB_VCODEC_X264)
2421 else if (vcodec == HB_VCODEC_FFMPEG)
2432 gint vquality = ghb_settings_get_dbl(settings, "video_quality");
2433 if (vquality < min || vquality > max)
2435 message = g_strdup_printf(
2436 "Interesting video quality choise: %d\n\n"
2437 "Typical values range from %d to %d.\n"
2438 "Are you sure you wish to use this setting?",
2439 vquality, min, max);
2440 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message,
2441 "Cancel", "Continue"))
2453 ghb_add_job(job_settings_t *js, gint unique_id)
2458 GHashTable *settings = js->settings;
2459 static gchar *x264opts;
2462 g_debug("ghb_add_job()\n");
2463 if (h == NULL) return;
2464 list = hb_get_titles( h );
2465 if( !hb_list_count( list ) )
2467 /* No valid title, stop right there */
2468 g_message("No title found.\n");
2472 gint titleindex = ghb_settings_get_index(settings, "title");
2473 title = hb_list_item( list, titleindex );
2474 if (title == NULL) return;
2476 /* Set job settings */
2478 if (job == NULL) return;
2480 job->mux = ghb_settings_get_int(settings, "container");
2481 if (job->mux == HB_MUX_MP4)
2483 job->largeFileSize = ghb_settings_get_bool(settings, "large_mp4");
2484 job->mp4_optimize = ghb_settings_get_bool(settings, "http_optimize_mp4");
2488 job->largeFileSize = FALSE;
2489 job->mp4_optimize = FALSE;
2491 gint chapter_start, chapter_end;
2492 chapter_start = ghb_settings_get_int(settings, "start_chapter");
2493 chapter_end = ghb_settings_get_int(settings, "end_chapter");
2494 gint num_chapters = hb_list_count(title->list_chapter);
2495 job->chapter_start = MIN( num_chapters, chapter_start );
2496 job->chapter_end = MAX( job->chapter_start, chapter_end );
2498 job->chapter_markers = ghb_settings_get_bool(settings, "chapter_markers");
2499 if ( job->chapter_markers )
2503 for(chapter = chapter_start; chapter <= chapter_end; chapter++)
2505 hb_chapter_t * chapter_s;
2508 if (js->chapter_list == NULL || js->chapter_list[chapter-1] == 0)
2510 name = g_strdup_printf ("Chapter %2d", chapter);
2514 name = g_strdup(js->chapter_list[chapter-1]);
2516 chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
2517 strncpy(chapter_s->title, name, 1023);
2518 chapter_s->title[1023] = '\0';
2522 job->crop[0] = ghb_settings_get_int(settings, "crop_top");
2523 job->crop[1] = ghb_settings_get_int(settings, "crop_bottom");
2524 job->crop[2] = ghb_settings_get_int(settings, "crop_left");
2525 job->crop[3] = ghb_settings_get_int(settings, "crop_right");
2528 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2529 gint deint = ghb_settings_get_int(settings, "deinterlace");
2531 job->deinterlace = (deint == 0) ? 0 : 1;
2533 job->deinterlace = 0;
2534 job->grayscale = ghb_settings_get_bool(settings, "grayscale");
2536 gboolean anamorphic = ghb_settings_get_bool(settings, "anamorphic");
2537 gboolean round_dimensions = ghb_settings_get_bool(settings, "round_dimensions");
2538 if (round_dimensions && anamorphic)
2540 job->pixel_ratio = 2;
2543 else if (anamorphic)
2545 // Huh! I thought I wanted to use pixel_ratio 1 for this case, but
2546 // when its 1, libhb discards the width and height and uses original
2547 // title dims - crop. Thats not what I want.
2548 // Also, x264 requires things to divisible by 2.
2549 job->pixel_ratio = 2;
2554 job->pixel_ratio = 0;
2557 job->vfr = ghb_settings_get_bool(settings, "variable_frame_rate");
2558 /* Add selected filters */
2559 job->filters = hb_list_init();
2560 if( ghb_settings_get_bool(settings, "detelecine" ) || job->vfr )
2562 hb_filter_detelecine.settings = NULL;
2563 hb_list_add( job->filters, &hb_filter_detelecine );
2567 // Use default settings
2568 hb_filter_decomb.settings = NULL;
2569 hb_list_add( job->filters, &hb_filter_decomb );
2571 if( job->deinterlace )
2573 hb_filter_deinterlace.settings = (gchar*)ghb_settings_get_string(settings, "deinterlace");
2574 hb_list_add( job->filters, &hb_filter_deinterlace );
2576 if( ghb_settings_get_bool(settings, "deblock") )
2578 hb_filter_deblock.settings = NULL;
2579 hb_list_add( job->filters, &hb_filter_deblock );
2581 gint denoise = ghb_settings_get_int(settings, "denoise");
2584 hb_filter_denoise.settings = (gchar*)ghb_settings_get_string(settings, "denoise");
2585 hb_list_add( job->filters, &hb_filter_denoise );
2587 job->width = ghb_settings_get_int(settings, "scale_width");
2588 job->height = ghb_settings_get_int(settings, "scale_height");
2590 job->vcodec = ghb_settings_get_int(settings, "video_codec");
2591 if ((job->mux == HB_MUX_MP4 || job->mux == HB_MUX_AVI) &&
2592 (job->vcodec == HB_VCODEC_THEORA))
2594 // mp4|avi/theora combination is not supported.
2595 job->vcodec = HB_VCODEC_XVID;
2597 if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
2599 job->ipod_atom = ghb_settings_get_bool(settings, "ipod_file");
2601 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2603 gdouble vquality = ghb_settings_get_dbl(settings, "video_quality");
2604 if (!ghb_settings_get_bool(settings, "directqp"))
2607 if (ghb_settings_get_bool(settings, "linear_vquality"))
2609 if (job->vcodec == HB_VCODEC_X264)
2611 // Adjust to same range as xvid and ffmpeg
2612 vquality = 31.0 - vquality * 31.0;
2615 // Convert linear to log curve
2616 vquality = 12 + 6 * log2(vquality);
2617 if (vquality > 51) vquality = 51;
2618 if (vquality < 1) vquality = 1;
2626 if (vquality == 0.0) vquality = 0.01;
2627 if (vquality == 1.0) vquality = 0.0;
2630 job->vquality = vquality;
2633 else if (ghb_settings_get_bool(settings, "vquality_type_bitrate"))
2635 job->vquality = -1.0;
2636 job->vbitrate = ghb_settings_get_int(settings, "video_bitrate");
2638 // AVI container does not support variable frame rate.
2639 if (job->mux == HB_MUX_AVI)
2644 gint vrate = ghb_settings_get_int(settings, "framerate");
2645 if( vrate == 0 || job->vfr )
2647 job->vrate = title->rate;
2648 job->vrate_base = title->rate_base;
2653 job->vrate = 27000000;
2654 job->vrate_base = vrate;
2657 // First remove any audios that are already in the list
2658 // This happens if you are encoding the same title a second time.
2659 gint num_audio_tracks = hb_list_count(job->list_audio);
2661 for(ii = 0; ii < num_audio_tracks; ii++)
2663 hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
2664 hb_list_rem(job->list_audio, audio);
2666 GSList *link = js->audio_settings;
2668 while (link != NULL)
2670 GHashTable *asettings;
2671 hb_audio_config_t audio;
2672 hb_audio_config_t *taudio;
2674 hb_audio_config_init(&audio);
2675 asettings = (GHashTable*)link->data;
2676 audio.in.track = ghb_settings_get_index(asettings, "audio_track");
2677 audio.out.track = count;
2678 audio.out.codec = ghb_settings_get_int(asettings, "audio_codec");
2679 taudio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, audio.in.track );
2680 if ((taudio->in.codec != HB_ACODEC_AC3) && (audio.out.codec == HB_ACODEC_AC3))
2682 // Not supported. AC3 is passthrough only, so input must be AC3
2683 if (job->mux == HB_MUX_AVI)
2685 audio.out.codec = HB_ACODEC_LAME;
2689 audio.out.codec = HB_ACODEC_FAAC;
2692 if ((job->mux == HB_MUX_MP4) &&
2693 ((audio.out.codec == HB_ACODEC_LAME) ||
2694 (audio.out.codec == HB_ACODEC_VORBIS)))
2696 // mp4/mp3|vorbis combination is not supported.
2697 audio.out.codec = HB_ACODEC_FAAC;
2699 if ((job->mux == HB_MUX_AVI) &&
2700 ((audio.out.codec == HB_ACODEC_FAAC) ||
2701 (audio.out.codec == HB_ACODEC_VORBIS)))
2703 // avi/faac|vorbis combination is not supported.
2704 audio.out.codec = HB_ACODEC_LAME;
2706 if ((job->mux == HB_MUX_OGM) &&
2707 ((audio.out.codec == HB_ACODEC_FAAC) ||
2708 (audio.out.codec == HB_ACODEC_AC3)))
2710 // ogm/faac|ac3 combination is not supported.
2711 audio.out.codec = HB_ACODEC_VORBIS;
2713 audio.out.dynamic_range_compression = ghb_settings_get_dbl(asettings, "audio_drc");
2714 // It would be better if this were done in libhb for us, but its not yet.
2715 if (audio.out.codec == HB_ACODEC_AC3 || audio.out.codec == HB_ACODEC_DCA)
2717 audio.out.mixdown = 0;
2721 audio.out.mixdown = ghb_settings_get_int (asettings, "audio_mix");
2722 // Make sure the mixdown is valid and pick a new one if not.
2723 audio.out.mixdown = ghb_get_best_mix(titleindex, audio.in.track, audio.out.codec,
2725 audio.out.bitrate = ghb_settings_get_int(asettings, "audio_bitrate") / 1000;
2726 gint srate = ghb_settings_get_int(asettings, "audio_sample_rate");
2727 if (srate == 0) // 0 is same as source
2728 audio.out.samplerate = taudio->in.samplerate;
2730 audio.out.samplerate = srate;
2733 // Add it to the jobs audio list
2734 hb_audio_add( job, &audio );
2738 // I was tempted to move this up with the reset of the video quality
2739 // settings, but I suspect the settings above need to be made
2740 // first in order for hb_calc_bitrate to be accurate.
2741 if (ghb_settings_get_bool(settings, "vquality_type_target"))
2745 size = ghb_settings_get_int(settings, "video_target_size");
2746 job->vbitrate = hb_calc_bitrate( job, size );
2747 job->vquality = -1.0;
2750 job->file = ghb_settings_get_string(settings, "destination");
2751 job->crf = ghb_settings_get_bool(settings, "constant_rate_factor");
2752 // TODO: libhb holds onto a reference to the x264opts and is not
2753 // finished with it until encoding the job is done. But I can't
2754 // find a way to get at the job before it is removed in order to
2755 // free up the memory I am allocating here.
2756 // The short story is THIS LEAKS.
2757 x264opts = ghb_build_x264opts_string(settings);
2759 if( x264opts != NULL && *x264opts != '\0' )
2761 job->x264opts = x264opts;
2763 else /*avoids a bus error crash when options aren't specified*/
2765 job->x264opts = NULL;
2767 gint subtitle = ghb_settings_get_int(settings, "subtitle_lang");
2768 gboolean forced_subtitles = ghb_settings_get_bool (settings, "forced_subtitles");
2769 job->subtitle_force = forced_subtitles;
2771 job->subtitle = subtitle;
2776 // Subtitle scan. Look for subtitle matching audio language
2780 * When subtitle scan is enabled do a fast pre-scan job
2781 * which will determine which subtitles to enable, if any.
2784 job->indepth_scan = 1;
2786 x264opts_tmp = job->x264opts;
2787 job->x264opts = NULL;
2789 job->select_subtitle = malloc(sizeof(hb_subtitle_t*));
2790 *(job->select_subtitle) = NULL;
2793 * Add the pre-scan job
2795 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2797 //if (job->x264opts != NULL)
2798 // g_free(job->x264opts);
2800 job->x264opts = x264opts_tmp;
2804 job->select_subtitle = NULL;
2806 if( ghb_settings_get_bool(settings, "two_pass") &&
2807 !ghb_settings_get_bool(settings, "vquality_type_constant"))
2810 * If subtitle_scan is enabled then only turn it on
2811 * for the second pass and then off again for the
2814 hb_subtitle_t **subtitle_tmp = job->select_subtitle;
2815 job->select_subtitle = NULL;
2817 job->indepth_scan = 0;
2818 gchar *x264opts2 = NULL;
2821 x264opts2 = g_strdup(x264opts);
2824 * If turbo options have been selected then append them
2825 * to the x264opts now (size includes one ':' and the '\0')
2827 if( ghb_settings_get_bool(settings, "turbo") )
2833 tmp_x264opts = g_strdup_printf("%s:%s", x264opts, turbo_opts);
2839 * No x264opts to modify, but apply the turbo options
2840 * anyway as they may be modifying defaults
2842 tmp_x264opts = g_strdup_printf("%s", turbo_opts);
2844 x264opts = tmp_x264opts;
2846 job->x264opts = x264opts;
2848 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2850 //if (job->x264opts != NULL)
2851 // g_free(job->x264opts);
2853 job->select_subtitle = subtitle_tmp;
2856 * On the second pass we turn off subtitle scan so that we
2857 * can actually encode using any subtitles that were auto
2858 * selected in the first pass (using the whacky select-subtitle
2859 * attribute of the job).
2861 job->indepth_scan = 0;
2862 job->x264opts = x264opts2;
2863 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2865 //if (job->x264opts != NULL)
2866 // g_free(job->x264opts);
2870 job->indepth_scan = 0;
2872 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2874 //if (job->x264opts != NULL)
2875 // g_free(job->x264opts);
2880 ghb_remove_job(gint unique_id)
2885 // Multiples passes all get the same id
2887 // Go backwards through list, so reordering doesn't screw me.
2888 ii = hb_count(h) - 1;
2889 while ((job = hb_job(h, ii--)) != NULL)
2891 if ((job->sequence_id & 0xFFFFFF) == unique_id)
2912 hb_get_state2( h, &s );
2914 if( s.state == HB_STATE_PAUSED )
2925 ghb_get_preview_image(gint titleindex, gint index, GHashTable *settings, gboolean borders)
2930 list = hb_get_titles( h );
2931 if( !hb_list_count( list ) )
2933 /* No valid title, stop right there */
2936 title = hb_list_item( list, titleindex );
2937 if (title == NULL) return NULL;
2938 if (title->job == NULL) return NULL;
2939 set_preview_job_settings(title->job, settings);
2941 // hb_get_preview can't handle sizes that are larger than the original title
2943 if (title->job->width > title->width)
2944 title->job->width = title->width;
2946 if (title->job->height > title->height)
2947 title->job->height = title->height;
2948 // And also creates artifacts if the width is not a multiple of 8
2949 //title->job->width = ((title->job->width + 4) >> 3) << 3;
2950 // And the height must be a multiple of 2
2951 //title->job->height = ((title->job->height + 1) >> 1) << 1;
2953 // Make sure we have a big enough buffer to receive the image from libhb. libhb
2954 // creates images with a one-pixel border around the original content. Hence we
2955 // add 2 pixels horizontally and vertically to the buffer size.
2956 gint srcWidth = title->width + 2;
2957 gint srcHeight= title->height + 2;
2958 gint dstWidth = title->width;
2959 gint dstHeight= title->height;
2961 gint borderLeft = 1;
2964 // |<---------- title->width ----------->|
2965 // | |<---- title->job->width ---->| |
2967 // .......................................
2968 // ....+-----------------------------+....
2969 // ....| |....<-- gray border
2972 // ....| |<------- image
2978 // ....+-----------------------------+....
2979 // .......................................
2980 dstWidth = title->job->width;
2981 dstHeight = title->job->height;
2982 borderTop = (srcHeight - dstHeight) / 2;
2983 borderLeft = (srcWidth - dstWidth) / 2;
2984 g_debug("boarders removed\n");
2987 g_debug("src %d x %d\n", srcWidth, srcHeight);
2988 g_debug("dst %d x %d\n", dstWidth, dstHeight);
2989 g_debug("job dim %d x %d\n", title->job->width, title->job->height);
2990 g_debug("title crop %d:%d:%d:%d\n",
2995 g_debug("job crop %d:%d:%d:%d\n",
2996 title->job->crop[0],
2997 title->job->crop[1],
2998 title->job->crop[2],
2999 title->job->crop[3]);
3000 static guint8 *buffer = NULL;
3001 static gint bufferSize = 0;
3004 newSize = srcWidth * srcHeight * 4;
3005 if( bufferSize < newSize )
3007 bufferSize = newSize;
3008 buffer = (guint8*) g_realloc( buffer, bufferSize );
3010 hb_get_preview( h, title, index, buffer );
3012 // Create an GdkPixbuf and copy the libhb image into it, converting it from
3013 // libhb's format something suitable. Along the way, we'll strip off the
3014 // border around libhb's image.
3016 // The image data returned by hb_get_preview is 4 bytes per pixel, BGRA format.
3017 // Alpha is ignored.
3019 GdkPixbuf *preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, dstWidth, dstHeight);
3020 guint8 *pixels = gdk_pixbuf_get_pixels (preview);
3022 guint32 *src = (guint32*)buffer;
3023 guint8 *dst = pixels;
3024 src += borderTop * srcWidth; // skip top rows in src to get to first row of dst
3025 src += borderLeft; // skip left pixels in src to get to first pixel of dst
3027 gint channels = gdk_pixbuf_get_n_channels (preview);
3028 gint stride = gdk_pixbuf_get_rowstride (preview);
3030 for (ii = 0; ii < dstHeight; ii++)
3033 for (jj = 0; jj < dstWidth; jj++)
3035 tmp[0] = src[0] >> 16;
3036 tmp[1] = src[0] >> 8;
3037 tmp[2] = src[0] >> 0;
3042 src += (srcWidth - dstWidth); // skip to next row in src
3044 // Got it, but hb_get_preview doesn't compensate for anamorphic, so lets
3046 gint width, height, par_width, par_height;
3047 gboolean anamorphic = ghb_settings_get_bool (settings, "anamorphic");
3050 hb_set_anamorphic_size( title->job, &width, &height, &par_width, &par_height );
3051 if (par_width > par_height)
3052 dstWidth = dstWidth * par_width / par_height;
3054 dstHeight = dstHeight * par_height / par_width;
3057 g_debug("scaled %d x %d\n", dstWidth, dstHeight);
3058 GdkPixbuf *scaled_preview;
3059 scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
3060 g_object_unref (preview);
3061 return scaled_preview;
3065 sanitize_volname(gchar *name)
3090 ghb_dvd_volname(const gchar *device)
3093 name = hb_dvd_name((gchar*)device);
3096 sanitize_volname(name);
3097 return g_strdup(name);