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)
570 ghb_get_rate_string(gint rate, gint type)
578 index = search_rates(hb_video_rates, rate, hb_video_rates_count);
579 if (index >= 0) return hb_video_rates[index].string;
581 case GHB_AUDIO_BITRATE:
584 index = search_rates(hb_audio_bitrates, rate, hb_audio_bitrates_count);
585 if (index >= 0) return hb_audio_bitrates[index].string;
587 case GHB_AUDIO_SAMPLERATE:
589 index = search_rates(hb_audio_rates, rate, hb_audio_rates_count);
590 if (index >= 0) return hb_audio_rates[index].string;
597 static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter);
600 get_combo_box_store(GtkBuilder *builder, const gchar *name)
605 g_debug("get_combo_box_store() %s\n", name);
606 // First modify the combobox model to allow greying out of options
607 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
608 store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
613 grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey)
618 store = get_combo_box_store(builder, name);
619 if (find_combo_item_by_int(GTK_TREE_MODEL(store), value, &iter))
621 gtk_list_store_set(store, &iter,
628 ghb_grey_combo_options(GtkBuilder *builder)
631 gint container, track, titleindex, acodec;
633 hb_audio_config_t *audio = NULL;
635 widget = GHB_WIDGET (builder, "title");
636 titleindex = ghb_widget_int(widget);
637 widget = GHB_WIDGET (builder, "audio_track");
638 track = ghb_widget_int(widget);
639 audio = get_hb_audio(titleindex, track);
640 widget = GHB_WIDGET (builder, "container");
641 container = ghb_widget_int(widget);
642 widget = GHB_WIDGET (builder, "http_optimize_mp4");
643 httpopt = ghb_widget_int(widget);
645 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, FALSE);
646 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, FALSE);
647 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, FALSE);
648 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_LAME, FALSE);
649 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_LAME, FALSE);
650 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_LAME, FALSE);
651 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, FALSE);
652 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, FALSE);
653 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, FALSE);
655 gboolean allow_ac3 = TRUE;
657 !(container == HB_MUX_MP4 && httpopt) &&
658 (container != HB_MUX_OGM);
662 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, FALSE);
663 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_AC3, FALSE);
664 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_AC3, FALSE);
668 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, TRUE);
669 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_AC3, TRUE);
670 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_AC3, TRUE);
672 if (audio && audio->in.codec != HB_ACODEC_AC3)
674 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_AC3, TRUE);
676 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, FALSE);
678 widget = GHB_WIDGET (builder, "audio_codec");
679 acodec = ghb_widget_int(widget);
680 if (acodec != HB_ACODEC_AC3)
682 grey_combo_box_item(builder, "audio_mix", 0, TRUE);
684 if (container == HB_MUX_MP4)
686 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_LAME, TRUE);
687 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_LAME, TRUE);
688 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_LAME, TRUE);
689 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, TRUE);
690 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, TRUE);
691 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, TRUE);
692 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, TRUE);
694 else if (container == HB_MUX_AVI)
696 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, TRUE);
697 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, TRUE);
698 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, TRUE);
699 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_VORBIS, TRUE);
700 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_VORBIS, TRUE);
701 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_VORBIS, TRUE);
702 grey_combo_box_item(builder, "video_codec", HB_VCODEC_THEORA, TRUE);
704 else if (container == HB_MUX_OGM)
706 grey_combo_box_item(builder, "audio_codec", HB_ACODEC_FAAC, TRUE);
707 grey_combo_box_item(builder, "pref_audio_codec1", HB_ACODEC_FAAC, TRUE);
708 grey_combo_box_item(builder, "pref_audio_codec2", HB_ACODEC_FAAC, TRUE);
711 gboolean allow_mono = TRUE;
712 gboolean allow_stereo = TRUE;
713 gboolean allow_dolby = TRUE;
714 gboolean allow_dpl2 = TRUE;
715 gboolean allow_6ch = TRUE;
719 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
720 (acodec != HB_ACODEC_LAME);
721 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
723 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
725 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
726 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
727 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
728 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
730 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
731 (acodec != HB_ACODEC_LAME) &&
732 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
733 (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
735 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_MONO, !allow_mono);
736 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_STEREO, !allow_stereo);
737 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_DOLBY, !allow_dolby);
738 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
739 grey_combo_box_item(builder, "audio_mix", HB_AMIXDOWN_6CH, !allow_6ch);
743 ghb_get_best_mix(gint titleindex, gint track, gint acodec, gint mix)
745 hb_audio_config_t *audio = NULL;
746 gboolean allow_mono = TRUE;
747 gboolean allow_stereo = TRUE;
748 gboolean allow_dolby = TRUE;
749 gboolean allow_dpl2 = TRUE;
750 gboolean allow_6ch = TRUE;
752 if (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA))
754 // Audio codec pass-thru. No mixdown
757 audio = get_hb_audio(titleindex, track);
761 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
762 (acodec != HB_ACODEC_LAME);
763 gint layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
765 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
767 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
768 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
769 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
770 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
772 (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
773 (acodec != HB_ACODEC_LAME) &&
774 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
775 (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
777 gboolean greater = FALSE;
780 // If no mix is specified, select the best available.
781 mix = HB_AMIXDOWN_6CH;
783 if (mix == HB_AMIXDOWN_6CH)
786 if (allow_6ch) return HB_AMIXDOWN_6CH;
788 if (mix == HB_AMIXDOWN_DOLBYPLII || greater)
791 if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
793 if (mix == HB_AMIXDOWN_DOLBY || greater)
796 if (allow_dolby) return HB_AMIXDOWN_DOLBY;
798 if (mix == HB_AMIXDOWN_STEREO || greater)
801 if (allow_stereo) return HB_AMIXDOWN_STEREO;
803 if (mix == HB_AMIXDOWN_MONO || greater)
806 if (allow_mono) return HB_AMIXDOWN_MONO;
808 if (allow_stereo) return HB_AMIXDOWN_STEREO;
809 if (allow_dolby) return HB_AMIXDOWN_DOLBY;
810 if (allow_dpl2) return HB_AMIXDOWN_DOLBYPLII;
811 if (allow_6ch) return HB_AMIXDOWN_6CH;
815 // Set up the model for the combo box
817 init_combo_box(GtkBuilder *builder, const gchar *name)
821 GtkCellRenderer *cell;
823 g_debug("init_combo_box() %s\n", name);
824 // First modify the combobox model to allow greying out of options
825 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
827 // 1 - String to display
828 // 2 - bool indicating whether the entry is selectable (grey or not)
829 // 3 - String that is used for presets
830 // 4 - Int value determined by backend
831 // 5 - String value determined by backend
832 store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_BOOLEAN,
833 G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
834 gtk_combo_box_set_model(combo, GTK_TREE_MODEL(store));
836 gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo));
837 cell = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
838 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE);
839 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell,
840 "text", 0, "sensitive", 1, NULL);
844 audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
850 g_debug("audio_bitrate_opts_set ()\n");
851 store = get_combo_box_store(builder, name);
852 gtk_list_store_clear(store);
853 for (ii = 0; ii < count; ii++)
855 gtk_list_store_append(store, &iter);
856 gtk_list_store_set(store, &iter,
860 3, rates[ii].rate * 1000,
867 audio_bitrate_opts_clean(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
872 gboolean done = FALSE;
873 gboolean changed = FALSE;
875 g_debug("audio_bitrate_opts_clean ()\n");
876 store = get_combo_box_store(builder, name);
877 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter))
881 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1);
882 if (search_rates(rates, ivalue/1000, count) < 0)
884 done = !gtk_list_store_remove(store, &iter);
889 done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
897 audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
903 g_debug("audio_samplerate_opts_set ()\n");
904 store = get_combo_box_store(builder, name);
905 gtk_list_store_clear(store);
906 // Add an item for "Same As Source"
907 gtk_list_store_append(store, &iter);
908 gtk_list_store_set(store, &iter,
915 for (ii = 0; ii < count; ii++)
917 gtk_list_store_append(store, &iter);
918 gtk_list_store_set(store, &iter,
929 video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
935 g_debug("video_rate_opts_set ()\n");
936 store = get_combo_box_store(builder, name);
937 gtk_list_store_clear(store);
938 // Add an item for "Same As Source"
939 gtk_list_store_append(store, &iter);
940 gtk_list_store_set(store, &iter,
947 for (ii = 0; ii < count; ii++)
951 if (strcmp(rates[ii].string, "23.976") == 0)
953 desc = "(NTSC Film)";
955 else if (strcmp(rates[ii].string, "25") == 0)
957 desc = "(PAL Film/Video)";
959 else if (strcmp(rates[ii].string, "29.97") == 0)
961 desc = "(NTSC Video)";
963 option = g_strdup_printf ("%s %s", rates[ii].string, desc);
964 gtk_list_store_append(store, &iter);
965 gtk_list_store_set(store, &iter,
977 mix_opts_set(GtkBuilder *builder, const gchar *name)
983 g_debug("audio_bitrate_opts_set ()\n");
984 store = get_combo_box_store(builder, name);
985 gtk_list_store_clear(store);
986 gtk_list_store_append(store, &iter);
987 gtk_list_store_set(store, &iter,
994 for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
996 gtk_list_store_append(store, &iter);
997 gtk_list_store_set(store, &iter,
998 0, hb_audio_mixdowns[ii].human_readable_name,
1000 2, hb_audio_mixdowns[ii].short_name,
1001 3, hb_audio_mixdowns[ii].amixdown,
1002 4, hb_audio_mixdowns[ii].internal_name,
1008 language_opts_set(GtkBuilder *builder, const gchar *name)
1011 GtkListStore *store;
1014 g_debug("audio_bitrate_opts_set ()\n");
1015 store = get_combo_box_store(builder, name);
1016 gtk_list_store_clear(store);
1017 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1019 gtk_list_store_append(store, &iter);
1020 gtk_list_store_set(store, &iter,
1021 0, language_table[ii].eng_name,
1023 2, language_table[ii].iso639_2,
1025 4, language_table[ii].iso639_1,
1031 title_opts_set(GtkBuilder *builder, const gchar *name)
1034 GtkListStore *store;
1040 g_debug("title_opts_set ()\n");
1041 store = get_combo_box_store(builder, name);
1042 gtk_list_store_clear(store);
1045 list = hb_get_titles( h );
1046 count = hb_list_count( list );
1047 if (count > 100) count = 100;
1051 // No titles. Fill in a default.
1052 gtk_list_store_append(store, &iter);
1053 gtk_list_store_set(store, &iter,
1062 for (ii = 0; ii < count; ii++)
1066 title = (hb_title_t*)hb_list_item(list, ii);
1067 option = g_strdup_printf ("%d - %02dh%02dm%02ds",
1068 title->index, title->hours, title->minutes, title->seconds);
1069 gtk_list_store_append(store, &iter);
1070 gtk_list_store_set(store, &iter,
1081 find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter)
1084 gboolean foundit = FALSE;
1086 if (gtk_tree_model_get_iter_first (store, iter))
1090 gtk_tree_model_get(store, iter, 3, &ivalue, -1);
1091 if (value == ivalue)
1096 } while (gtk_tree_model_iter_next (store, iter));
1102 audio_rate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
1105 GtkListStore *store;
1108 g_debug("audio_rate_opts_add ()\n");
1109 store = get_combo_box_store(builder, name);
1110 if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
1112 str = g_strdup_printf ("%.8g", (gdouble)rate/1000.0);
1113 gtk_list_store_append(store, &iter);
1114 gtk_list_store_set(store, &iter,
1128 audio_rate_opts_remove(GtkBuilder *builder, const gchar *name, gint rate)
1131 GtkListStore *store;
1133 g_debug("audio_rate_opts_remove ()\n");
1134 store = get_combo_box_store(builder, name);
1135 if (find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
1137 gtk_list_store_remove (store, &iter);
1145 audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1148 GtkListStore *store;
1151 hb_audio_config_t * audio;
1155 g_debug("audio_track_opts_set ()\n");
1156 store = get_combo_box_store(builder, name);
1157 gtk_list_store_clear(store);
1160 list = hb_get_titles( h );
1161 title = (hb_title_t*)hb_list_item( list, titleindex );
1164 count = hb_list_count( title->list_audio );
1167 if (count > 10) count = 10;
1170 // No audio. set some default
1171 gtk_list_store_append(store, &iter);
1172 gtk_list_store_set(store, &iter,
1181 for (ii = 0; ii < count; ii++)
1183 audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, ii );
1184 gtk_list_store_append(store, &iter);
1185 gtk_list_store_set(store, &iter,
1186 0, audio->lang.description,
1188 2, audio->lang.description,
1190 4, audio->lang.description,
1196 subtitle_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
1199 GtkListStore *store;
1202 hb_subtitle_t * subtitle;
1206 g_debug("subtitle_opts_set ()\n");
1207 store = get_combo_box_store(builder, name);
1208 gtk_list_store_clear(store);
1211 list = hb_get_titles( h );
1212 title = (hb_title_t*)hb_list_item( list, titleindex );
1215 count = hb_list_count( title->list_subtitle );
1218 if (count > 10) count = 10;
1219 // Add options for "none" and "autoselect"
1220 gtk_list_store_append(store, &iter);
1221 gtk_list_store_set(store, &iter,
1228 gtk_list_store_append(store, &iter);
1229 gtk_list_store_set(store, &iter,
1236 for (ii = 0; ii < count; ii++)
1238 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, ii );
1239 gtk_list_store_append(store, &iter);
1240 gtk_list_store_set(store, &iter,
1243 2, subtitle->iso639_2,
1245 4, subtitle->iso639_2,
1248 if (titleindex == -1)
1250 for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
1252 gtk_list_store_append(store, &iter);
1253 gtk_list_store_set(store, &iter,
1254 0, language_table[ii].eng_name,
1256 2, language_table[ii].iso639_2,
1258 4, language_table[ii].iso639_2,
1271 guint64 longest = 0;
1272 gint titleindex = 0;
1274 g_debug("ghb_longest_title ()\n");
1275 if (h == NULL) return 0;
1276 list = hb_get_titles( h );
1277 count = hb_list_count( list );
1278 if (count > 100) count = 100;
1279 for (ii = 0; ii < count; ii++)
1281 title = (hb_title_t*)hb_list_item(list, ii);
1282 if (title->duration > longest)
1285 longest = title->duration;
1292 ghb_find_audio_track(gint titleindex, const gchar *lang, gint acodec)
1296 hb_audio_config_t * audio;
1301 g_debug("find_audio_track ()\n");
1304 list = hb_get_titles( h );
1305 title = (hb_title_t*)hb_list_item( list, titleindex );
1308 count = hb_list_count( title->list_audio );
1311 if (count > 10) count = 10;
1312 for (ii = 0; ii < count; ii++)
1314 audio = (hb_audio_config_t*)hb_list_audio_config_item( title->list_audio, ii );
1315 if ((strcmp(lang, audio->lang.iso639_2) == 0) ||
1316 (strcmp(lang, "und") == 0))
1318 // Candidate track. Will use if no better match found
1320 if (audio->in.codec == acodec)
1331 generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
1334 GtkListStore *store;
1337 g_debug("generic_opts_set ()\n");
1338 store = get_combo_box_store(builder, name);
1339 gtk_list_store_clear(store);
1340 for (ii = 0; ii < opts->count; ii++)
1342 gtk_list_store_append(store, &iter);
1343 gtk_list_store_set(store, &iter,
1344 0, opts->map[ii].option,
1346 2, opts->map[ii].shortOpt,
1347 3, opts->map[ii].ivalue,
1348 4, opts->map[ii].svalue,
1354 ghb_update_ui_combo_box(GtkBuilder *builder, const gchar *name, gint user_data, gboolean all)
1356 GtkComboBox *combo = NULL;
1358 gint handler_id = 0;
1360 g_debug("ghb_update_ui_combo_box() %s\n", name);
1363 // Clearing a combo box causes a rash of "changed" events, even when
1364 // the active item is -1 (inactive). To control things, I'm disabling
1365 // the event till things are settled down.
1366 combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
1367 signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX);
1370 // Valid signal id found. This should always succeed.
1371 handler_id = g_signal_handler_find ((gpointer)combo, G_SIGNAL_MATCH_ID,
1372 signal_id, 0, 0, 0, 0);
1375 // This should also always succeed
1376 g_signal_handler_block ((gpointer)combo, handler_id);
1380 if (all || strcmp(name, "audio_bitrate") == 0)
1381 audio_bitrate_opts_set(builder, "audio_bitrate", hb_audio_bitrates, hb_audio_bitrates_count);
1382 if (all || strcmp(name, "pref_audio_bitrate1") == 0)
1383 audio_bitrate_opts_set(builder, "pref_audio_bitrate1", hb_audio_bitrates, hb_audio_bitrates_count);
1384 if (all || strcmp(name, "pref_audio_bitrate2") == 0)
1385 audio_bitrate_opts_set(builder, "pref_audio_bitrate2", hb_audio_bitrates, hb_audio_bitrates_count);
1386 if (all || strcmp(name, "audio_sample_rate") == 0)
1387 audio_samplerate_opts_set(builder, "audio_sample_rate", hb_audio_rates, hb_audio_rates_count);
1388 if (all || strcmp(name, "pref_audio_rate1") == 0)
1389 audio_samplerate_opts_set(builder, "pref_audio_rate1", hb_audio_rates, hb_audio_rates_count);
1390 if (all || strcmp(name, "pref_audio_rate2") == 0)
1391 audio_samplerate_opts_set(builder, "pref_audio_rate2", hb_audio_rates, hb_audio_rates_count);
1392 if (all || strcmp(name, "framerate") == 0)
1393 video_rate_opts_set(builder, "framerate", hb_video_rates, hb_video_rates_count);
1394 if (all || strcmp(name, "audio_mix") == 0)
1395 mix_opts_set(builder, "audio_mix");
1396 if (all || strcmp(name, "pref_audio_mix1") == 0)
1397 mix_opts_set(builder, "pref_audio_mix1");
1398 if (all || strcmp(name, "pref_audio_mix2") == 0)
1399 mix_opts_set(builder, "pref_audio_mix2");
1400 if (all || strcmp(name, "pref_source_audio_lang") == 0)
1401 language_opts_set(builder, "pref_source_audio_lang");
1402 if (all || strcmp(name, "subtitle_lang") == 0)
1403 subtitle_opts_set(builder, "subtitle_lang", user_data);
1404 if (all || strcmp(name, "title") == 0)
1405 title_opts_set(builder, "title");
1406 if (all || strcmp(name, "audio_track") == 0)
1407 audio_track_opts_set(builder, "audio_track", user_data);
1408 if (all || strcmp(name, "container") == 0)
1409 generic_opts_set(builder, "container", &container_opts);
1410 if (all || strcmp(name, "deinterlace") == 0)
1411 generic_opts_set(builder, "deinterlace", &deint_opts);
1412 if (all || strcmp(name, "denoise") == 0)
1413 generic_opts_set(builder, "denoise", &denoise_opts);
1414 if (all || strcmp(name, "video_codec") == 0)
1415 generic_opts_set(builder, "video_codec", &vcodec_opts);
1416 if (all || strcmp(name, "audio_codec") == 0)
1417 generic_opts_set(builder, "audio_codec", &acodec_opts);
1418 if (all || strcmp(name, "pref_audio_codec1") == 0)
1419 generic_opts_set(builder, "pref_audio_codec1", &pref_acodec_opts);
1420 if (all || strcmp(name, "pref_audio_codec2") == 0)
1421 generic_opts_set(builder, "pref_audio_codec2", &pref_acodec_opts);
1422 if (all || strcmp(name, "pref_source_audio_codec") == 0)
1423 generic_opts_set(builder, "pref_source_audio_codec", &source_acodec_opts);
1424 if (all || strcmp(name, "x264_direct") == 0)
1425 generic_opts_set(builder, "x264_direct", &direct_opts);
1426 if (all || strcmp(name, "x264_me") == 0)
1427 generic_opts_set(builder, "x264_me", &me_opts);
1428 if (all || strcmp(name, "x264_subme") == 0)
1429 generic_opts_set(builder, "x264_subme", &subme_opts);
1430 if (all || strcmp(name, "x264_analyse") == 0)
1431 generic_opts_set(builder, "x264_analyse", &analyse_opts);
1432 if (all || strcmp(name, "x264_trellis") == 0)
1433 generic_opts_set(builder, "x264_trellis", &trellis_opts);
1436 g_signal_handler_unblock ((gpointer)combo, handler_id);
1441 init_ui_combo_boxes(GtkBuilder *builder)
1443 init_combo_box(builder, "audio_bitrate");
1444 init_combo_box(builder, "pref_audio_bitrate1");
1445 init_combo_box(builder, "pref_audio_bitrate2");
1446 init_combo_box(builder, "audio_sample_rate");
1447 init_combo_box(builder, "pref_audio_rate1");
1448 init_combo_box(builder, "pref_audio_rate2");
1449 init_combo_box(builder, "framerate");
1450 init_combo_box(builder, "audio_mix");
1451 init_combo_box(builder, "pref_audio_mix1");
1452 init_combo_box(builder, "pref_audio_mix2");
1453 init_combo_box(builder, "pref_source_audio_lang");
1454 init_combo_box(builder, "subtitle_lang");
1455 init_combo_box(builder, "title");
1456 init_combo_box(builder, "audio_track");
1457 init_combo_box(builder, "container");
1458 init_combo_box(builder, "deinterlace");
1459 init_combo_box(builder, "denoise");
1460 init_combo_box(builder, "video_codec");
1461 init_combo_box(builder, "audio_codec");
1462 init_combo_box(builder, "pref_audio_codec1");
1463 init_combo_box(builder, "pref_audio_codec2");
1464 init_combo_box(builder, "pref_source_audio_codec");
1465 init_combo_box(builder, "x264_direct");
1466 init_combo_box(builder, "x264_me");
1467 init_combo_box(builder, "x264_subme");
1468 init_combo_box(builder, "x264_analyse");
1469 init_combo_box(builder, "x264_trellis");
1472 static const char * turbo_opts =
1473 "ref=1:subme=1:me=dia:analyse=none:trellis=0:"
1474 "no-fast-pskip=0:8x8dct=0:weightb=0";
1476 // Construct the x264 options string
1477 // The result is allocated, so someone must free it at some point.
1479 ghb_build_x264opts_string(GHashTable *settings)
1481 GString *x264opts = g_string_new("");
1482 gint refs = ghb_settings_get_int(settings, "x264_refs");
1485 g_string_append_printf(x264opts, "ref=%d:", refs);
1489 if (ghb_settings_get_bool(settings, "x264_mixed_refs"))
1491 g_string_append(x264opts, "mixed-refs=1:");
1494 gint subme = ghb_settings_get_int(settings, "x264_subme");
1495 if (subme != 5) // 5 is default
1497 g_string_append_printf(x264opts, "subme=%d:", subme);
1499 gint bframes = ghb_settings_get_int(settings, "x264_bframes");
1502 g_string_append_printf(x264opts, "bframes=%d:", bframes);
1503 if (ghb_settings_get_bool(settings, "x264_weighted_bframes"))
1505 g_string_append(x264opts, "weightb=1:");
1509 if (ghb_settings_get_bool(settings, "x264_brdo"))
1511 g_string_append(x264opts, "brdo=1:");
1514 if (ghb_settings_get_bool(settings, "x264_bime"))
1516 g_string_append(x264opts, "bime=1:");
1521 if (ghb_settings_get_bool(settings, "x264_bpyramid"))
1523 g_string_append(x264opts, "b-pyramid=1:");
1526 if (ghb_settings_get_bool(settings, "x264_no_fast_pskip"))
1528 g_string_append(x264opts, "no-fast-pskip=1:");
1530 if (ghb_settings_get_bool(settings, "x264_no_dct_decimate"))
1532 g_string_append(x264opts, "no-dct-decimate=1:");
1534 if (!ghb_settings_get_bool(settings, "x264_cabac"))
1536 g_string_append(x264opts, "cabac=0:");
1540 gint trellis = ghb_settings_get_int(settings, "x264_trellis");
1541 if (trellis != 0); // != None
1543 g_string_append_printf(x264opts, "trellis=%d:", trellis);
1547 dba = ghb_settings_get_int(settings, "x264_deblock_alpha");
1548 dbb = ghb_settings_get_int(settings, "x264_deblock_beta");
1549 if (dba != 0 || dbb != 0)
1551 g_string_append_printf(x264opts, "deblock=%d,%d:", dba, dbb);
1553 const gchar *me = ghb_settings_get_string(settings, "x264_me");
1554 g_string_append_printf(x264opts, "me=%s:", me);
1555 gint analyse = ghb_settings_get_int(settings, "x264_analyse");
1556 if (analyse != 0) // != Some
1558 g_string_append_printf(x264opts, "analyse=%s:",
1559 ghb_settings_get_string(settings, "x264_analyse"));
1561 if (analyse != 1) // != none
1563 gint direct = ghb_settings_get_int(settings, "x264_direct");
1564 if (direct != 1) // !spatial
1566 g_string_append_printf(x264opts, "direct=%s:",
1567 ghb_settings_get_string(settings, "x264_direct"));
1570 g_string_append_printf(x264opts, "merange=%d:",
1571 ghb_settings_get_int(settings, "x264_merange"));
1573 const gchar *opts = ghb_settings_get_string(settings, "x264_options");
1574 if (opts != NULL && opts[0] != 0)
1576 g_string_append_printf(x264opts, "%s:", opts);
1578 // strip the trailing ":"
1581 result = g_string_free(x264opts, FALSE);
1582 len = strlen(result);
1583 if (len > 0) result[len - 1] = 0;
1588 ghb_get_chapters(gint titleindex)
1592 hb_chapter_t * chapter;
1594 gchar **result = NULL;
1596 g_debug("ghb_get_chapters (title = %d)\n", titleindex);
1597 if (h == NULL) return NULL;
1598 list = hb_get_titles( h );
1599 title = (hb_title_t*)hb_list_item( list, titleindex );
1600 if (title == NULL) return NULL;
1601 count = hb_list_count( title->list_chapter );
1602 result = g_malloc((count+1) * sizeof(gchar*));
1603 for (ii = 0; ii < count; ii++)
1605 chapter = hb_list_item(title->list_chapter, ii);
1606 if (chapter == NULL) break;
1607 if (chapter->title == NULL || chapter->title[0] == 0)
1608 result[ii] = g_strdup_printf ("Chapter %2d", ii);
1610 result[ii] = g_strdup(chapter->title);
1617 ghb_ac3_in_audio_list(GSList *audio_list)
1622 while (link != NULL)
1624 GHashTable *asettings;
1627 asettings = (GHashTable*)link->data;
1628 acodec = ghb_settings_get_int(asettings, "audio_codec");
1629 if (acodec == HB_ACODEC_AC3)
1637 ghb_set_passthru_rate_opts(GtkBuilder *builder, gint bitrate)
1639 gboolean changed = FALSE;
1640 changed = audio_rate_opts_add(builder, "audio_bitrate", bitrate);
1645 ghb_set_default_rate_opts(GtkBuilder *builder)
1647 gboolean changed = FALSE;
1648 changed = audio_bitrate_opts_clean(builder, "audio_bitrate", hb_audio_bitrates, hb_audio_bitrates_count);
1652 static ghb_status_t hb_status;
1655 ghb_backend_init(GtkBuilder *builder, gint debug, gint update)
1658 h = hb_init( debug, update );
1659 // Set up the list model for the combos
1660 init_ui_combo_boxes(builder);
1661 // Populate all the combos
1662 ghb_update_ui_combo_box(builder, NULL, 0, TRUE);
1666 ghb_backend_scan(const gchar *path, gint titleindex)
1668 hb_scan( h, path, titleindex );
1669 hb_status.state |= GHB_STATE_SCANNING;
1676 static gint scan_complete_count = 0;
1679 hb_get_state( h, &s );
1680 scans = hb_get_scancount(h);
1681 if (scans > scan_complete_count)
1683 hb_status.state &= ~GHB_STATE_SCANNING;
1684 hb_status.state |= GHB_STATE_SCANDONE;
1685 scan_complete_count = hb_get_scancount(h);
1693 #define p s.param.scanning
1694 case HB_STATE_SCANNING:
1696 hb_status.state |= GHB_STATE_SCANNING;
1697 hb_status.title_count = p.title_count;
1698 hb_status.title_cur = p.title_cur;
1702 case HB_STATE_SCANDONE:
1704 hb_status.state &= ~GHB_STATE_SCANNING;
1705 hb_status.state |= GHB_STATE_SCANDONE;
1708 #define p s.param.working
1709 case HB_STATE_WORKING:
1710 hb_status.state |= GHB_STATE_WORKING;
1711 hb_status.state &= ~GHB_STATE_PAUSED;
1712 hb_status.job_cur = p.job_cur;
1713 hb_status.job_count = p.job_count;
1714 hb_status.progress = p.progress;
1715 hb_status.rate_cur = p.rate_cur;
1716 hb_status.rate_avg = p.rate_avg;
1717 hb_status.hours = p.hours;
1718 hb_status.minutes = p.minutes;
1719 hb_status.seconds = p.seconds;
1720 hb_status.unique_id = p.sequence_id & 0xFFFFFF;
1724 case HB_STATE_PAUSED:
1725 hb_status.state |= GHB_STATE_PAUSED;
1728 #define p s.param.muxing
1729 case HB_STATE_MUXING:
1731 hb_status.state |= GHB_STATE_MUXING;
1735 #define p s.param.workdone
1736 case HB_STATE_WORKDONE:
1740 hb_status.state |= GHB_STATE_WORKDONE;
1741 hb_status.state &= ~GHB_STATE_MUXING;
1742 hb_status.state &= ~GHB_STATE_PAUSED;
1743 hb_status.state &= ~GHB_STATE_WORKING;
1744 hb_status.error = p.error;
1745 // Delete all remaining jobs of this encode.
1746 // An encode can be composed of multiple associated jobs.
1747 // When a job is stopped, libhb removes it from the job list,
1748 // but does not remove other jobs that may be associated with it.
1749 // Associated jobs are taged in the sequence id.
1750 while (((job = hb_job(h, 0)) != NULL) && ((job->sequence_id >> 24) != 0) )
1758 ghb_backend_events(signal_user_data_t *ud, gint *unique_id)
1761 GtkProgressBar *progress;
1763 if (h == NULL) return GHB_EVENT_NONE;
1765 progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
1766 *unique_id = hb_status.unique_id;
1767 if (hb_status.state & GHB_STATE_SCANNING)
1769 status = g_strdup_printf ("Scanning title %d of %d...",
1770 hb_status.title_cur, hb_status.title_count );
1771 gtk_progress_bar_set_text (progress, status);
1773 gtk_progress_bar_set_fraction (progress,
1774 (gdouble)hb_status.title_cur / hb_status.title_count);
1776 else if (hb_status.state & GHB_STATE_SCANDONE)
1778 status = g_strdup_printf ("Scan done");
1779 gtk_progress_bar_set_text (progress, status);
1781 gtk_progress_bar_set_fraction (progress, 1.0);
1782 hb_status.state &= ~GHB_STATE_SCANDONE;
1783 return GHB_EVENT_SCAN_DONE;
1785 else if (hb_status.state & GHB_STATE_WORKING)
1787 if(hb_status.seconds > -1)
1789 status= g_strdup_printf(
1790 "Encoding: task %d of %d, %.2f %%"
1791 " (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)",
1792 hb_status.job_cur, hb_status.job_count,
1793 100.0 * hb_status.progress,
1794 hb_status.rate_cur, hb_status.rate_avg, hb_status.hours,
1795 hb_status.minutes, hb_status.seconds );
1799 status= g_strdup_printf(
1800 "Encoding: task %d of %d, %.2f %%",
1801 hb_status.job_cur, hb_status.job_count,
1802 100.0 * hb_status.progress );
1804 gtk_progress_bar_set_text (progress, status);
1805 gtk_progress_bar_set_fraction (progress, hb_status.progress);
1807 return GHB_EVENT_WORKING;
1809 else if (hb_status.state & GHB_STATE_WORKDONE)
1811 switch( hb_status.error )
1814 gtk_progress_bar_set_text( progress, "Rip done!" );
1816 case HB_ERROR_CANCELED:
1817 gtk_progress_bar_set_text( progress, "Rip canceled." );
1818 return GHB_EVENT_WORK_CANCELED;
1821 gtk_progress_bar_set_text( progress, "Rip failed.");
1823 gtk_progress_bar_set_fraction (progress, 1.0);
1824 hb_status.state &= ~GHB_STATE_WORKDONE;
1825 return GHB_EVENT_WORK_DONE;
1827 else if (hb_status.state & GHB_STATE_PAUSED)
1829 status = g_strdup_printf ("Paused");
1830 gtk_progress_bar_set_text (progress, status);
1832 return GHB_EVENT_PAUSED;
1834 else if (hb_status.state & GHB_STATE_MUXING)
1836 gtk_progress_bar_set_text(progress, "Muxing: this may take awhile...");
1838 return GHB_EVENT_NONE;
1842 ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
1847 if (h == NULL) return FALSE;
1848 list = hb_get_titles( h );
1849 if( !hb_list_count( list ) )
1851 /* No valid title, stop right there */
1855 title = hb_list_item( list, titleindex );
1856 if (title == NULL) return FALSE; // Bad titleindex
1857 tinfo->width = title->width;
1858 tinfo->height = title->height;
1859 memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
1860 // Don't allow crop to 0
1861 if (title->crop[0] + title->crop[1] >= title->height)
1862 title->crop[0] = title->crop[1] = 0;
1863 if (title->crop[2] + title->crop[3] >= title->width)
1864 title->crop[2] = title->crop[3] = 0;
1865 tinfo->num_chapters = hb_list_count(title->list_chapter);
1866 tinfo->rate_base = title->rate_base;
1867 tinfo->rate = title->rate;
1868 hb_reduce(&(tinfo->aspect_n), &(tinfo->aspect_d),
1869 title->width * title->pixel_aspect_width,
1870 title->height * title->pixel_aspect_height);
1871 tinfo->hours = title->hours;
1872 tinfo->minutes = title->minutes;
1873 tinfo->seconds = title->seconds;
1878 ghb_get_audio_info(ghb_audio_info_t *ainfo, gint titleindex, gint audioindex)
1880 hb_audio_config_t *audio;
1882 audio = get_hb_audio(titleindex, audioindex);
1883 if (audio == NULL) return FALSE; // Bad audioindex
1884 ainfo->codec = audio->in.codec;
1885 ainfo->bitrate = audio->in.bitrate;
1886 ainfo->samplerate = audio->in.samplerate;
1891 ghb_audio_is_passthru(gint acodec)
1893 g_debug("ghb_audio_is_passthru () \n");
1894 g_debug("acodec %d\n", acodec);
1895 return (acodec == HB_ACODEC_AC3);
1899 ghb_get_default_acodec()
1901 return HB_ACODEC_FAAC;
1905 ghb_set_scale(signal_user_data_t *ud, gint mode)
1910 GHashTable *settings = ud->settings;
1911 gboolean keep_aspect, round_dims, anamorphic;
1912 gboolean autocrop, autoscale, noscale;
1913 gint crop[4], width, height, par_width, par_height;
1914 gint crop_width, crop_height;
1915 gint aspect_n, aspect_d;
1916 gboolean keep_width = (mode == GHB_SCALE_KEEP_WIDTH);
1917 gboolean keep_height = (mode == GHB_SCALE_KEEP_HEIGHT);
1923 gint max_height = 0;
1925 g_debug("ghb_set_scale ()\n");
1927 if (h == NULL) return;
1928 list = hb_get_titles( h );
1929 if( !hb_list_count( list ) )
1931 /* No valid title, stop right there */
1934 gint titleindex = ghb_settings_get_index(settings, "title");
1935 title = hb_list_item( list, titleindex );
1936 if (title == NULL) return;
1938 if (job == NULL) return;
1940 // First configure widgets
1941 round_dims = ghb_settings_get_bool(ud->settings, "round_dimensions");
1942 anamorphic = ghb_settings_get_bool(ud->settings, "anamorphic");
1943 keep_aspect = ghb_settings_get_bool(ud->settings, "keep_aspect");
1944 autocrop = ghb_settings_get_bool(ud->settings, "autocrop");
1945 autoscale = ghb_settings_get_bool(ud->settings, "autoscale");
1946 // "Noscale" is a flag that says we prefer to crop extra to satisfy
1947 // alignment constraints rather than scaling to satisfy them.
1948 noscale = ghb_settings_get_bool(ud->settings, "noscale");
1949 // Align dimensions to either 16 or 2 pixels
1950 // The scaler crashes if the dimensions are not divisible by 2
1951 // x264 also will not accept dims that are not multiple of 2
1952 modshift = round_dims ? 4 : 1;
1953 modround = round_dims ? 8 : 1;
1957 keep_height = FALSE;
1959 if (anamorphic || keep_aspect)
1961 keep_height = FALSE;
1963 // Step needs to be at least 2 because odd widths cause scaler crash
1964 step = round_dims ? 16 : 2;
1965 widget = GHB_WIDGET (ud->builder, "scale_width");
1966 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
1967 widget = GHB_WIDGET (ud->builder, "scale_height");
1968 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16);
1971 ghb_title_info_t tinfo;
1973 if (ghb_get_title_info (&tinfo, titleindex))
1975 crop[0] = tinfo.crop[0];
1976 crop[1] = tinfo.crop[1];
1977 crop[2] = tinfo.crop[2];
1978 crop[3] = tinfo.crop[3];
1983 // Adjust the cropping to accomplish the desired width and height
1984 crop_width = tinfo.width - crop[2] - crop[3];
1985 crop_height = tinfo.height - crop[0] - crop[1];
1986 width = (crop_width >> modshift) << modshift;
1987 height = (crop_height >> modshift) << modshift;
1988 need1 = (crop_height - height) / 2;
1989 need2 = crop_height - height - need1;
1992 need1 = (crop_width - width) / 2;
1993 need2 = crop_width - width - need1;
1997 ghb_ui_update_int (ud, "crop_top", crop[0]);
1998 ghb_ui_update_int (ud, "crop_bottom", crop[1]);
1999 ghb_ui_update_int (ud, "crop_left", crop[2]);
2000 ghb_ui_update_int (ud, "crop_right", crop[3]);
2003 crop[0] = ghb_settings_get_int(ud->settings, "crop_top");
2004 crop[1] = ghb_settings_get_int(ud->settings, "crop_bottom");
2005 crop[2] = ghb_settings_get_int(ud->settings, "crop_left");
2006 crop[3] = ghb_settings_get_int(ud->settings, "crop_right");
2007 hb_reduce(&aspect_n, &aspect_d,
2008 title->width * title->pixel_aspect_width,
2009 title->height * title->pixel_aspect_height);
2010 crop_width = title->width - crop[2] - crop[3];
2011 crop_height = title->height - crop[0] - crop[1];
2015 height = crop_height;
2016 max_width = crop_width;
2017 max_height = crop_height;
2021 width = ghb_settings_get_int(ud->settings, "scale_width");
2022 height = ghb_settings_get_int(ud->settings, "scale_height");
2023 max_width = ghb_settings_get_int(ud->settings, "max_width");
2024 max_height = ghb_settings_get_int(ud->settings, "max_width");
2026 max_width = (max_width >> modshift) << modshift;
2027 max_height = (max_height >> modshift) << modshift;
2028 // Adjust dims according to max values
2031 max_height = crop_height;
2035 max_width = crop_width;
2037 height = MIN(height, max_height);
2038 width = MIN(width, max_width);
2039 g_debug("max_width %d, max_height %d\n", max_width, max_height);
2042 width = title->width - crop[2] - crop[3];
2044 height = title->height - crop[0] - crop[1];
2054 // The scaler crashes if the dimensions are not divisible by 2
2055 // Align mod 2. And so does something in x264_encoder_headers()
2060 job->maxHeight = max_height;
2061 job->crop[0] = crop[0]; job->crop[1] = crop[1];
2062 job->crop[2] = crop[2]; job->crop[3] = crop[3];
2063 hb_set_anamorphic_size( job, &width, &height, &par_width, &par_height );
2070 gint new_width, new_height;
2072 g_debug("kw %s kh %s\n", keep_width ? "y":"n", keep_height ? "y":"n");
2073 g_debug("w %d h %d\n", width, height);
2074 // Compute pixel aspect ration.
2075 par = (gdouble)(title->height * aspect_n) / (title->width * aspect_d);
2076 // Must scale so that par becomes 1:1
2077 // Try to keep largest dimension
2078 new_height = (crop_height * ((gdouble)width/crop_width) / par);
2079 new_width = (crop_width * ((gdouble)height/crop_height) * par);
2080 // Height and width are always multiples of 2, so do the rounding
2081 new_height = ((new_height + 1) >> 1) << 1;
2082 new_width = ((new_width + 1) >> 1) << 1;
2083 g_debug("max w %d, new w %d\n", max_width, new_width);
2084 if (max_width && (new_width > max_width))
2086 height = new_height;
2088 else if (max_height && (new_height > max_height))
2092 else if (keep_width)
2094 height = new_height;
2096 else if (keep_height)
2100 else if (width > new_width)
2102 height = new_height;
2108 g_debug("new w %d h %d\n", width, height);
2110 width = ((width + modround) >> modshift) << modshift;
2111 height = ((height + modround) >> modshift) << modshift;
2113 ghb_ui_update_int (ud, "scale_width", width);
2114 ghb_ui_update_int (ud, "scale_height", height);
2118 set_preview_job_settings(hb_job_t *job, GHashTable *settings)
2120 job->crop[0] = ghb_settings_get_int(settings, "crop_top");
2121 job->crop[1] = ghb_settings_get_int(settings, "crop_bottom");
2122 job->crop[2] = ghb_settings_get_int(settings, "crop_left");
2123 job->crop[3] = ghb_settings_get_int(settings, "crop_right");
2125 gboolean anamorphic = ghb_settings_get_bool(settings, "anamorphic");
2126 gboolean round_dimensions = ghb_settings_get_bool(settings, "round_dimensions");
2127 if (round_dimensions && anamorphic)
2130 job->pixel_ratio = 2;
2132 else if (anamorphic)
2135 job->pixel_ratio = 2;
2140 job->pixel_ratio = 0;
2142 job->width = ghb_settings_get_int(settings, "scale_width");
2143 job->height = ghb_settings_get_int(settings, "scale_height");
2144 gint deint = ghb_settings_get_int(settings, "deinterlace");
2145 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2146 job->deinterlace = (!decomb && deint == 0) ? 0 : 1;
2150 ghb_calculate_target_bitrate(GHashTable *settings, gint titleindex)
2157 if (h == NULL) return 2000;
2158 list = hb_get_titles( h );
2159 title = hb_list_item( list, titleindex );
2160 if (title == NULL) return 2000;
2162 if (job == NULL) return 2000;
2163 size = ghb_settings_get_int(settings, "video_target_size");
2164 return hb_calc_bitrate( job, size );
2168 ghb_guess_bitrate(GHashTable *settings)
2171 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2173 // This is really rough. I'm trying to err on the high
2174 // side since this is used to estimate if there is
2175 // sufficient disk space left
2176 gint vcodec = ghb_settings_get_int(settings, "video_codec");
2177 gdouble vquality = ghb_settings_get_dbl(settings, "video_quality")/100;
2178 if (vcodec == HB_VCODEC_X264 &&
2179 !ghb_settings_get_bool(settings, "linear_vquality"))
2181 vquality = 51.0 - vquality * 51.0;
2182 // Convert log curve to linear
2183 vquality = exp2((vquality-12)/6);
2184 // Don't let it go to 0
2185 if (vquality >= 31) vquality = 30;
2186 vquality = (31 - vquality) / 31;
2188 // bitrate seems to be a log relasionship to quality
2189 // with typical source material
2190 // This is a real wag
2191 bitrate = 20*1024*1024*exp10(vquality*14)/exp10(14);
2192 // Add some bits for audio
2193 bitrate += 500*1024;
2197 // Add some fudge to the bitrate to leave breathing room
2198 bitrate = ghb_settings_get_int(settings, "video_bitrate")*1024;
2199 // Add some bits for audio
2200 bitrate += 500*1024;
2206 ghb_validate_video(signal_user_data_t *ud)
2208 GHashTable *settings = ud->settings;
2212 mux = ghb_settings_get_int(settings, "container");
2213 vcodec = ghb_settings_get_int(settings, "video_codec");
2214 if ((mux == HB_MUX_MP4 || mux == HB_MUX_AVI) &&
2215 (vcodec == HB_VCODEC_THEORA))
2217 // mp4|avi/theora combination is not supported.
2218 message = g_strdup_printf(
2219 "Theora is not supported in the MP4 and AVI containers.\n\n"
2220 "You should choose a different video codec or container.\n"
2221 "If you continue, XviD will be chosen for you.");
2222 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2228 vcodec = HB_VCODEC_XVID;
2229 ghb_ui_update_int(ud, "video_codec", vcodec);
2231 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2232 gboolean vfr = ghb_settings_get_bool(settings, "variable_frame_rate");
2235 message = g_strdup_printf(
2236 "Decomb is intended to be used in conjunction\n"
2237 "with variable frame rate.\n\n"
2238 "Would you like me to enable VFR for you?");
2239 if (ghb_message_dialog(GTK_MESSAGE_WARNING, message, "No", "Yes"))
2241 ghb_ui_update_int(ud, "variable_frame_rate", TRUE);
2249 ghb_validate_container(signal_user_data_t *ud)
2254 container = ghb_settings_get_bool(ud->settings, "container");
2255 if (container == HB_MUX_MP4)
2258 httpopt = ghb_settings_get_bool(ud->settings, "http_optimize_mp4");
2259 if (httpopt && ghb_ac3_in_audio_list(ud->audio_settings))
2261 message = g_strdup_printf(
2262 "AC3 audio in HTTP optimized MP4 is not supported.\n\n"
2263 "You should choose a different audio codec.\n"
2264 "If you continue, FAAC will be chosen for you.");
2265 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2271 GSList *link = ud->audio_settings;
2272 while (link != NULL)
2274 GHashTable *asettings;
2275 asettings = (GHashTable*)link->data;
2276 gint acodec = ghb_settings_get_int(asettings, "audio_codec");
2277 if (acodec == HB_ACODEC_AC3)
2279 setting_value_t *value;
2280 value = get_acodec_value(HB_ACODEC_FAAC);
2281 ghb_settings_set(asettings, "audio_codec", value);
2291 ghb_validate_audio(signal_user_data_t *ud)
2295 GHashTable *settings = ud->settings;
2297 setting_value_t *value;
2299 if (h == NULL) return FALSE;
2300 list = hb_get_titles( h );
2301 if( !hb_list_count( list ) )
2303 /* No valid title, stop right there */
2304 g_message("No title found.\n");
2308 gint titleindex = ghb_settings_get_index(settings, "title");
2309 title = hb_list_item( list, titleindex );
2310 if (title == NULL) return FALSE;
2311 GSList *link = ud->audio_settings;
2312 gint mux = ghb_settings_get_int(settings, "container");
2313 while (link != NULL)
2315 GHashTable *asettings;
2316 hb_audio_config_t *taudio;
2318 asettings = (GHashTable*)link->data;
2319 gint track = ghb_settings_get_index(asettings, "audio_track");
2320 gint codec = ghb_settings_get_int(asettings, "audio_codec");
2321 taudio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, track );
2322 if ((taudio->in.codec != HB_ACODEC_AC3) && (codec == HB_ACODEC_AC3))
2324 // Not supported. AC3 is passthrough only, so input must be AC3
2325 message = g_strdup_printf(
2326 "The source does not support AC3 Pass-Thru.\n\n"
2327 "You should choose a different audio codec.\n"
2328 "If you continue, one will be chosen for you.");
2329 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2335 if (mux == HB_MUX_AVI)
2337 codec = HB_ACODEC_LAME;
2341 codec = HB_ACODEC_FAAC;
2343 value = get_acodec_value(codec);
2344 ghb_settings_set(asettings, "audio_codec", value);
2346 gchar *a_unsup = NULL;
2347 gchar *mux_s = NULL;
2348 if (mux == HB_MUX_MP4)
2351 // mp4/mp3|vorbis combination is not supported.
2352 if (codec == HB_ACODEC_LAME)
2355 codec = HB_ACODEC_FAAC;
2357 if (codec == HB_ACODEC_VORBIS)
2360 codec = HB_ACODEC_FAAC;
2363 else if (mux == HB_MUX_AVI)
2366 // avi/faac|vorbis combination is not supported.
2367 if (codec == HB_ACODEC_FAAC)
2370 codec = HB_ACODEC_LAME;
2372 if (codec == HB_ACODEC_VORBIS)
2375 codec = HB_ACODEC_LAME;
2378 else if (mux == HB_MUX_OGM)
2381 // avi/faac|vorbis combination is not supported.
2382 if (codec == HB_ACODEC_FAAC)
2385 codec = HB_ACODEC_VORBIS;
2387 if (codec == HB_ACODEC_AC3)
2390 codec = HB_ACODEC_VORBIS;
2395 message = g_strdup_printf(
2396 "%s is not supported in the %s container.\n\n"
2397 "You should choose a different audio codec.\n"
2398 "If you continue, one will be chosen for you.", a_unsup, mux_s);
2399 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2405 value = get_acodec_value(codec);
2406 ghb_settings_set(asettings, "audio_codec", value);
2408 gint mix = ghb_settings_get_int (asettings, "audio_mix");
2409 gboolean allow_mono = TRUE;
2410 gboolean allow_stereo = TRUE;
2411 gboolean allow_dolby = TRUE;
2412 gboolean allow_dpl2 = TRUE;
2413 gboolean allow_6ch = TRUE;
2415 (taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
2416 (codec != HB_ACODEC_LAME);
2417 gint layout = taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
2419 ((layout == HB_INPUT_CH_LAYOUT_MONO && !allow_mono) || layout >= HB_INPUT_CH_LAYOUT_STEREO);
2421 (layout == HB_INPUT_CH_LAYOUT_3F1R) ||
2422 (layout == HB_INPUT_CH_LAYOUT_3F2R) ||
2423 (layout == HB_INPUT_CH_LAYOUT_DOLBY);
2424 allow_dpl2 = (layout == HB_INPUT_CH_LAYOUT_3F2R);
2426 (taudio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
2427 (codec != HB_ACODEC_LAME) &&
2428 (layout == HB_INPUT_CH_LAYOUT_3F2R) &&
2429 (taudio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE);
2431 gchar *mix_unsup = NULL;
2432 if (mix == HB_AMIXDOWN_MONO && !allow_mono)
2436 if (mix == HB_AMIXDOWN_STEREO && !allow_stereo)
2438 mix_unsup = "stereo";
2440 if (mix == HB_AMIXDOWN_DOLBY && !allow_dolby)
2442 mix_unsup = "Dolby";
2444 if (mix == HB_AMIXDOWN_DOLBYPLII && !allow_dpl2)
2446 mix_unsup = "Dolby Pro Logic II";
2448 if (mix == HB_AMIXDOWN_6CH && !allow_6ch)
2450 mix_unsup = "6 Channel";
2454 message = g_strdup_printf(
2455 "The source audio does not support %s mixdown.\n\n"
2456 "You should choose a different mixdown.\n"
2457 "If you continue, one will be chosen for you.", mix_unsup);
2458 if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
2464 mix = ghb_get_best_mix(titleindex, track, codec, mix);
2465 value = get_amix_value(mix);
2466 ghb_settings_set(asettings, "audio_mix", value);
2474 ghb_validate_vquality(GHashTable *settings)
2480 if (ghb_settings_get_bool(settings, "nocheckvquality")) return TRUE;
2481 vcodec = ghb_settings_get_int(settings, "video_codec");
2482 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2484 if (!ghb_settings_get_bool(settings, "directqp"))
2486 if (vcodec != HB_VCODEC_X264 ||
2487 ghb_settings_get_bool(settings, "linear_vquality"))
2492 else if (vcodec == HB_VCODEC_X264)
2500 if (vcodec == HB_VCODEC_X264)
2505 else if (vcodec == HB_VCODEC_FFMPEG)
2516 gint vquality = ghb_settings_get_dbl(settings, "video_quality");
2517 if (vquality < min || vquality > max)
2519 message = g_strdup_printf(
2520 "Interesting video quality choise: %d\n\n"
2521 "Typical values range from %d to %d.\n"
2522 "Are you sure you wish to use this setting?",
2523 vquality, min, max);
2524 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message,
2525 "Cancel", "Continue"))
2537 ghb_add_job(job_settings_t *js, gint unique_id)
2542 GHashTable *settings = js->settings;
2543 static gchar *x264opts;
2546 g_debug("ghb_add_job()\n");
2547 if (h == NULL) return;
2548 list = hb_get_titles( h );
2549 if( !hb_list_count( list ) )
2551 /* No valid title, stop right there */
2552 g_message("No title found.\n");
2556 gint titleindex = ghb_settings_get_index(settings, "title");
2557 title = hb_list_item( list, titleindex );
2558 if (title == NULL) return;
2560 /* Set job settings */
2562 if (job == NULL) return;
2564 job->mux = ghb_settings_get_int(settings, "container");
2565 if (job->mux == HB_MUX_MP4)
2567 job->largeFileSize = ghb_settings_get_bool(settings, "large_mp4");
2568 job->mp4_optimize = ghb_settings_get_bool(settings, "http_optimize_mp4");
2572 job->largeFileSize = FALSE;
2573 job->mp4_optimize = FALSE;
2575 gint chapter_start, chapter_end;
2576 chapter_start = ghb_settings_get_int(settings, "start_chapter");
2577 chapter_end = ghb_settings_get_int(settings, "end_chapter");
2578 gint num_chapters = hb_list_count(title->list_chapter);
2579 job->chapter_start = MIN( num_chapters, chapter_start );
2580 job->chapter_end = MAX( job->chapter_start, chapter_end );
2582 job->chapter_markers = ghb_settings_get_bool(settings, "chapter_markers");
2583 if ( job->chapter_markers )
2587 for(chapter = chapter_start; chapter <= chapter_end; chapter++)
2589 hb_chapter_t * chapter_s;
2592 if (js->chapter_list == NULL || js->chapter_list[chapter-1] == 0)
2594 name = g_strdup_printf ("Chapter %2d", chapter);
2598 name = g_strdup(js->chapter_list[chapter-1]);
2600 chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
2601 strncpy(chapter_s->title, name, 1023);
2602 chapter_s->title[1023] = '\0';
2606 job->crop[0] = ghb_settings_get_int(settings, "crop_top");
2607 job->crop[1] = ghb_settings_get_int(settings, "crop_bottom");
2608 job->crop[2] = ghb_settings_get_int(settings, "crop_left");
2609 job->crop[3] = ghb_settings_get_int(settings, "crop_right");
2612 gboolean decomb = ghb_settings_get_bool(settings, "decomb");
2613 gint deint = ghb_settings_get_int(settings, "deinterlace");
2615 job->deinterlace = (deint == 0) ? 0 : 1;
2617 job->deinterlace = 0;
2618 job->grayscale = ghb_settings_get_bool(settings, "grayscale");
2620 gboolean anamorphic = ghb_settings_get_bool(settings, "anamorphic");
2621 gboolean round_dimensions = ghb_settings_get_bool(settings, "round_dimensions");
2622 if (round_dimensions && anamorphic)
2624 job->pixel_ratio = 2;
2627 else if (anamorphic)
2629 // Huh! I thought I wanted to use pixel_ratio 1 for this case, but
2630 // when its 1, libhb discards the width and height and uses original
2631 // title dims - crop. Thats not what I want.
2632 // Also, x264 requires things to divisible by 2.
2633 job->pixel_ratio = 2;
2638 job->pixel_ratio = 0;
2641 job->vfr = ghb_settings_get_bool(settings, "variable_frame_rate");
2642 /* Add selected filters */
2643 job->filters = hb_list_init();
2644 if( ghb_settings_get_bool(settings, "detelecine" ) || job->vfr )
2646 hb_filter_detelecine.settings = NULL;
2647 hb_list_add( job->filters, &hb_filter_detelecine );
2651 // Use default settings
2652 hb_filter_decomb.settings = NULL;
2653 hb_list_add( job->filters, &hb_filter_decomb );
2655 if( job->deinterlace )
2657 hb_filter_deinterlace.settings = (gchar*)ghb_settings_get_string(settings, "deinterlace");
2658 hb_list_add( job->filters, &hb_filter_deinterlace );
2660 if( ghb_settings_get_bool(settings, "deblock") )
2662 hb_filter_deblock.settings = NULL;
2663 hb_list_add( job->filters, &hb_filter_deblock );
2665 gint denoise = ghb_settings_get_int(settings, "denoise");
2668 hb_filter_denoise.settings = (gchar*)ghb_settings_get_string(settings, "denoise");
2669 hb_list_add( job->filters, &hb_filter_denoise );
2671 job->width = ghb_settings_get_int(settings, "scale_width");
2672 job->height = ghb_settings_get_int(settings, "scale_height");
2674 job->vcodec = ghb_settings_get_int(settings, "video_codec");
2675 if ((job->mux == HB_MUX_MP4 || job->mux == HB_MUX_AVI) &&
2676 (job->vcodec == HB_VCODEC_THEORA))
2678 // mp4|avi/theora combination is not supported.
2679 job->vcodec = HB_VCODEC_XVID;
2681 if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
2683 job->ipod_atom = ghb_settings_get_bool(settings, "ipod_file");
2685 if (ghb_settings_get_bool(settings, "vquality_type_constant"))
2687 gdouble vquality = ghb_settings_get_dbl(settings, "video_quality");
2688 if (!ghb_settings_get_bool(settings, "directqp"))
2691 if (ghb_settings_get_bool(settings, "linear_vquality"))
2693 if (job->vcodec == HB_VCODEC_X264)
2695 // Adjust to same range as xvid and ffmpeg
2696 vquality = 31.0 - vquality * 31.0;
2699 // Convert linear to log curve
2700 vquality = 12 + 6 * log2(vquality);
2701 if (vquality > 51) vquality = 51;
2702 if (vquality < 1) vquality = 1;
2710 if (vquality == 0.0) vquality = 0.01;
2711 if (vquality == 1.0) vquality = 0.0;
2714 job->vquality = vquality;
2717 else if (ghb_settings_get_bool(settings, "vquality_type_bitrate"))
2719 job->vquality = -1.0;
2720 job->vbitrate = ghb_settings_get_int(settings, "video_bitrate");
2722 // AVI container does not support variable frame rate.
2723 if (job->mux == HB_MUX_AVI)
2728 gint vrate = ghb_settings_get_int(settings, "framerate");
2729 if( vrate == 0 || job->vfr )
2731 job->vrate = title->rate;
2732 job->vrate_base = title->rate_base;
2737 job->vrate = 27000000;
2738 job->vrate_base = vrate;
2741 // First remove any audios that are already in the list
2742 // This happens if you are encoding the same title a second time.
2743 gint num_audio_tracks = hb_list_count(job->list_audio);
2745 for(ii = 0; ii < num_audio_tracks; ii++)
2747 hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
2748 hb_list_rem(job->list_audio, audio);
2750 GSList *link = js->audio_settings;
2752 while (link != NULL)
2754 GHashTable *asettings;
2755 hb_audio_config_t audio;
2756 hb_audio_config_t *taudio;
2758 hb_audio_config_init(&audio);
2759 asettings = (GHashTable*)link->data;
2760 audio.in.track = ghb_settings_get_index(asettings, "audio_track");
2761 audio.out.track = count;
2762 audio.out.codec = ghb_settings_get_int(asettings, "audio_codec");
2763 taudio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, audio.in.track );
2764 if ((taudio->in.codec != HB_ACODEC_AC3) && (audio.out.codec == HB_ACODEC_AC3))
2766 // Not supported. AC3 is passthrough only, so input must be AC3
2767 if (job->mux == HB_MUX_AVI)
2769 audio.out.codec = HB_ACODEC_LAME;
2773 audio.out.codec = HB_ACODEC_FAAC;
2776 if ((job->mux == HB_MUX_MP4) &&
2777 ((audio.out.codec == HB_ACODEC_LAME) ||
2778 (audio.out.codec == HB_ACODEC_VORBIS)))
2780 // mp4/mp3|vorbis combination is not supported.
2781 audio.out.codec = HB_ACODEC_FAAC;
2783 if ((job->mux == HB_MUX_AVI) &&
2784 ((audio.out.codec == HB_ACODEC_FAAC) ||
2785 (audio.out.codec == HB_ACODEC_VORBIS)))
2787 // avi/faac|vorbis combination is not supported.
2788 audio.out.codec = HB_ACODEC_LAME;
2790 if ((job->mux == HB_MUX_OGM) &&
2791 ((audio.out.codec == HB_ACODEC_FAAC) ||
2792 (audio.out.codec == HB_ACODEC_AC3)))
2794 // ogm/faac|ac3 combination is not supported.
2795 audio.out.codec = HB_ACODEC_VORBIS;
2797 audio.out.dynamic_range_compression = ghb_settings_get_dbl(asettings, "audio_drc");
2798 // It would be better if this were done in libhb for us, but its not yet.
2799 if (audio.out.codec == HB_ACODEC_AC3 || audio.out.codec == HB_ACODEC_DCA)
2801 audio.out.mixdown = 0;
2805 audio.out.mixdown = ghb_settings_get_int (asettings, "audio_mix");
2806 // Make sure the mixdown is valid and pick a new one if not.
2807 audio.out.mixdown = ghb_get_best_mix(titleindex, audio.in.track, audio.out.codec,
2809 audio.out.bitrate = ghb_settings_get_int(asettings, "audio_bitrate") / 1000;
2810 gint srate = ghb_settings_get_int(asettings, "audio_sample_rate");
2811 if (srate == 0) // 0 is same as source
2812 audio.out.samplerate = taudio->in.samplerate;
2814 audio.out.samplerate = srate;
2817 // Add it to the jobs audio list
2818 hb_audio_add( job, &audio );
2822 // I was tempted to move this up with the reset of the video quality
2823 // settings, but I suspect the settings above need to be made
2824 // first in order for hb_calc_bitrate to be accurate.
2825 if (ghb_settings_get_bool(settings, "vquality_type_target"))
2829 size = ghb_settings_get_int(settings, "video_target_size");
2830 job->vbitrate = hb_calc_bitrate( job, size );
2831 job->vquality = -1.0;
2834 job->file = ghb_settings_get_string(settings, "destination");
2835 job->crf = ghb_settings_get_bool(settings, "constant_rate_factor");
2836 // TODO: libhb holds onto a reference to the x264opts and is not
2837 // finished with it until encoding the job is done. But I can't
2838 // find a way to get at the job before it is removed in order to
2839 // free up the memory I am allocating here.
2840 // The short story is THIS LEAKS.
2841 x264opts = ghb_build_x264opts_string(settings);
2843 if( x264opts != NULL && *x264opts != '\0' )
2845 job->x264opts = x264opts;
2847 else /*avoids a bus error crash when options aren't specified*/
2849 job->x264opts = NULL;
2851 gint subtitle = ghb_settings_get_int(settings, "subtitle_lang");
2852 gboolean forced_subtitles = ghb_settings_get_bool (settings, "forced_subtitles");
2853 job->subtitle_force = forced_subtitles;
2855 job->subtitle = subtitle;
2860 // Subtitle scan. Look for subtitle matching audio language
2864 * When subtitle scan is enabled do a fast pre-scan job
2865 * which will determine which subtitles to enable, if any.
2868 job->indepth_scan = 1;
2870 x264opts_tmp = job->x264opts;
2871 job->x264opts = NULL;
2873 job->select_subtitle = malloc(sizeof(hb_subtitle_t*));
2874 *(job->select_subtitle) = NULL;
2877 * Add the pre-scan job
2879 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2881 //if (job->x264opts != NULL)
2882 // g_free(job->x264opts);
2884 job->x264opts = x264opts_tmp;
2888 job->select_subtitle = NULL;
2890 if( ghb_settings_get_bool(settings, "two_pass") &&
2891 !ghb_settings_get_bool(settings, "vquality_type_constant"))
2894 * If subtitle_scan is enabled then only turn it on
2895 * for the second pass and then off again for the
2898 hb_subtitle_t **subtitle_tmp = job->select_subtitle;
2899 job->select_subtitle = NULL;
2901 job->indepth_scan = 0;
2902 gchar *x264opts2 = NULL;
2905 x264opts2 = g_strdup(x264opts);
2908 * If turbo options have been selected then append them
2909 * to the x264opts now (size includes one ':' and the '\0')
2911 if( ghb_settings_get_bool(settings, "turbo") )
2917 tmp_x264opts = g_strdup_printf("%s:%s", x264opts, turbo_opts);
2923 * No x264opts to modify, but apply the turbo options
2924 * anyway as they may be modifying defaults
2926 tmp_x264opts = g_strdup_printf("%s", turbo_opts);
2928 x264opts = tmp_x264opts;
2930 job->x264opts = x264opts;
2932 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2934 //if (job->x264opts != NULL)
2935 // g_free(job->x264opts);
2937 job->select_subtitle = subtitle_tmp;
2940 * On the second pass we turn off subtitle scan so that we
2941 * can actually encode using any subtitles that were auto
2942 * selected in the first pass (using the whacky select-subtitle
2943 * attribute of the job).
2945 job->indepth_scan = 0;
2946 job->x264opts = x264opts2;
2947 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2949 //if (job->x264opts != NULL)
2950 // g_free(job->x264opts);
2954 job->indepth_scan = 0;
2956 job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
2958 //if (job->x264opts != NULL)
2959 // g_free(job->x264opts);
2964 ghb_remove_job(gint unique_id)
2969 // Multiples passes all get the same id
2971 // Go backwards through list, so reordering doesn't screw me.
2972 ii = hb_count(h) - 1;
2973 while ((job = hb_job(h, ii--)) != NULL)
2975 if ((job->sequence_id & 0xFFFFFF) == unique_id)
2996 hb_get_state2( h, &s );
2998 if( s.state == HB_STATE_PAUSED )
3009 ghb_get_preview_image(gint titleindex, gint index, GHashTable *settings, gboolean borders)
3014 list = hb_get_titles( h );
3015 if( !hb_list_count( list ) )
3017 /* No valid title, stop right there */
3020 title = hb_list_item( list, titleindex );
3021 if (title == NULL) return NULL;
3022 if (title->job == NULL) return NULL;
3023 set_preview_job_settings(title->job, settings);
3025 // hb_get_preview can't handle sizes that are larger than the original title
3027 if (title->job->width > title->width)
3028 title->job->width = title->width;
3030 if (title->job->height > title->height)
3031 title->job->height = title->height;
3032 // And also creates artifacts if the width is not a multiple of 8
3033 //title->job->width = ((title->job->width + 4) >> 3) << 3;
3034 // And the height must be a multiple of 2
3035 //title->job->height = ((title->job->height + 1) >> 1) << 1;
3037 // Make sure we have a big enough buffer to receive the image from libhb. libhb
3038 // creates images with a one-pixel border around the original content. Hence we
3039 // add 2 pixels horizontally and vertically to the buffer size.
3040 gint srcWidth = title->width + 2;
3041 gint srcHeight= title->height + 2;
3042 gint dstWidth = title->width;
3043 gint dstHeight= title->height;
3045 gint borderLeft = 1;
3048 // |<---------- title->width ----------->|
3049 // | |<---- title->job->width ---->| |
3051 // .......................................
3052 // ....+-----------------------------+....
3053 // ....| |....<-- gray border
3056 // ....| |<------- image
3062 // ....+-----------------------------+....
3063 // .......................................
3064 dstWidth = title->job->width;
3065 dstHeight = title->job->height;
3066 borderTop = (srcHeight - dstHeight) / 2;
3067 borderLeft = (srcWidth - dstWidth) / 2;
3068 g_debug("boarders removed\n");
3071 g_debug("src %d x %d\n", srcWidth, srcHeight);
3072 g_debug("dst %d x %d\n", dstWidth, dstHeight);
3073 g_debug("job dim %d x %d\n", title->job->width, title->job->height);
3074 g_debug("title crop %d:%d:%d:%d\n",
3079 g_debug("job crop %d:%d:%d:%d\n",
3080 title->job->crop[0],
3081 title->job->crop[1],
3082 title->job->crop[2],
3083 title->job->crop[3]);
3084 static guint8 *buffer = NULL;
3085 static gint bufferSize = 0;
3088 newSize = srcWidth * srcHeight * 4;
3089 if( bufferSize < newSize )
3091 bufferSize = newSize;
3092 buffer = (guint8*) g_realloc( buffer, bufferSize );
3094 hb_get_preview( h, title, index, buffer );
3096 // Create an GdkPixbuf and copy the libhb image into it, converting it from
3097 // libhb's format something suitable. Along the way, we'll strip off the
3098 // border around libhb's image.
3100 // The image data returned by hb_get_preview is 4 bytes per pixel, BGRA format.
3101 // Alpha is ignored.
3103 GdkPixbuf *preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, dstWidth, dstHeight);
3104 guint8 *pixels = gdk_pixbuf_get_pixels (preview);
3106 guint32 *src = (guint32*)buffer;
3107 guint8 *dst = pixels;
3108 src += borderTop * srcWidth; // skip top rows in src to get to first row of dst
3109 src += borderLeft; // skip left pixels in src to get to first pixel of dst
3111 gint channels = gdk_pixbuf_get_n_channels (preview);
3112 gint stride = gdk_pixbuf_get_rowstride (preview);
3114 for (ii = 0; ii < dstHeight; ii++)
3117 for (jj = 0; jj < dstWidth; jj++)
3119 tmp[0] = src[0] >> 16;
3120 tmp[1] = src[0] >> 8;
3121 tmp[2] = src[0] >> 0;
3126 src += (srcWidth - dstWidth); // skip to next row in src
3128 // Got it, but hb_get_preview doesn't compensate for anamorphic, so lets
3130 gint width, height, par_width, par_height;
3131 gboolean anamorphic = ghb_settings_get_bool (settings, "anamorphic");
3134 hb_set_anamorphic_size( title->job, &width, &height, &par_width, &par_height );
3135 if (par_width > par_height)
3136 dstWidth = dstWidth * par_width / par_height;
3138 dstHeight = dstHeight * par_height / par_width;
3141 g_debug("scaled %d x %d\n", dstWidth, dstHeight);
3142 GdkPixbuf *scaled_preview;
3143 scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
3144 g_object_unref (preview);
3145 return scaled_preview;
3149 sanitize_volname(gchar *name)
3174 ghb_dvd_volname(const gchar *device)
3177 name = hb_dvd_name((gchar*)device);
3180 sanitize_volname(name);
3181 return g_strdup(name);