diff options
author | jstebbins <[email protected]> | 2010-09-28 22:10:49 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2010-09-28 22:10:49 +0000 |
commit | 03b2ce0e91c4e4ed44445a075ef5f35bc052b5b8 (patch) | |
tree | 24a1def4ca91cba98676508c6a3b1482ba131cb5 | |
parent | f1997be4ed1dd373316ac842685f18a6f8ab05ba (diff) |
SSA subtitle burn in
Anime fans rejoice! This patch adds SSA subtitle burn-in support with libass.
Therefore SSA subtitles should now be rendered in full quality, with the
appropriate embedded fonts and positioning information.
Thanks to davidfstr
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3557 b64f7644-9d1e-0410-96f1-a4d463321fa5
32 files changed, 1083 insertions, 158 deletions
diff --git a/contrib/fontconfig/A00-mingw-disableShared.patch b/contrib/fontconfig/A00-mingw-disableShared.patch new file mode 100644 index 000000000..1fd7474b1 --- /dev/null +++ b/contrib/fontconfig/A00-mingw-disableShared.patch @@ -0,0 +1,73 @@ +--- fontconfig-2.8.0/configure 2009-11-18 15:49:41.000000000 -0800 ++++ fontconfig-2.8.0/configure 2010-09-09 21:23:24.000000000 -0700 +@@ -825,6 +825,8 @@ + ms_librarian + OS_WIN32_FALSE + OS_WIN32_TRUE ++OS_WIN32_ENABLE_SHARED_TRUE ++OS_WIN32_ENABLE_SHARED_FALSE + LTCXXCOMPILE + LTCOMPILE + DOLT_BASH +@@ -11782,6 +11784,14 @@ + OS_WIN32_FALSE= + fi + ++ if test "$os_win32-$enable_shared" = "yes-yes"; then ++ OS_WIN32_ENABLE_SHARED_TRUE= ++ OS_WIN32_ENABLE_SHARED_FALSE='#' ++else ++ OS_WIN32_ENABLE_SHARED_TRUE='#' ++ OS_WIN32_ENABLE_SHARED_FALSE= ++fi ++ + + if test "$os_win32" = "yes"; then + # Extract the first word of "lib.exe", so it can be a program name with args. +@@ -15155,6 +15165,13 @@ + Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } + fi ++if test -z "${OS_WIN32_ENABLE_SHARED_TRUE}" && test -z "${OS_WIN32_ENABLE_SHARED_FALSE}"; then ++ { { echo "$as_me:$LINENO: error: conditional \"OS_WIN32_ENABLE_SHARED\" was never defined. ++Usually this means the macro was only invoked conditionally." >&5 ++echo "$as_me: error: conditional \"OS_WIN32_ENABLE_SHARED\" was never defined. ++Usually this means the macro was only invoked conditionally." >&2;} ++ { (exit 1); exit 1; }; } ++fi + if test -z "${MS_LIB_AVAILABLE_TRUE}" && test -z "${MS_LIB_AVAILABLE_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"MS_LIB_AVAILABLE\" was never defined. + Usually this means the macro was only invoked conditionally." >&5 +--- fontconfig-2.8.0/configure.in 2009-11-18 15:49:23.000000000 -0800 ++++ fontconfig-2.8.0/configure.in 2010-09-09 21:11:37.000000000 -0700 +@@ -76,6 +76,7 @@ + os_win32=no + esac + AM_CONDITIONAL(OS_WIN32, test "$os_win32" = "yes") ++AM_CONDITIONAL(OS_WIN32_ENABLE_SHARED, test "$os_win32-$enable_shared" = "yes-yes") + + if test "$os_win32" = "yes"; then + AC_CHECK_PROG(ms_librarian, lib.exe, yes, no) +--- fontconfig-2.8.0/src/Makefile.am 2010-09-09 21:12:43.000000000 -0700 ++++ fontconfig-2.8.0/src/Makefile.am 2010-09-09 21:13:07.000000000 -0700 +@@ -30,7 +30,9 @@ + # gcc import library install/uninstall + + install-libtool-import-lib: ++if OS_WIN32_ENABLE_SHARED + $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir) ++endif + $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def + + uninstall-libtool-import-lib: +--- fontconfig-2.8.0/src/Makefile.in 2009-11-18 15:49:39.000000000 -0800 ++++ fontconfig-2.8.0/src/Makefile.in 2010-09-09 21:14:38.000000000 -0700 +@@ -688,7 +688,7 @@ + # gcc import library install/uninstall + + @OS_WIN32_TRUE@install-libtool-import-lib: +-@OS_WIN32_TRUE@ $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir) ++@OS_WIN32_ENABLE_SHARED_TRUE@@OS_WIN32_TRUE@ $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir) + @OS_WIN32_TRUE@ $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def + + @OS_WIN32_TRUE@uninstall-libtool-import-lib: diff --git a/contrib/fontconfig/module.defs b/contrib/fontconfig/module.defs new file mode 100644 index 000000000..ce96c8235 --- /dev/null +++ b/contrib/fontconfig/module.defs @@ -0,0 +1,71 @@ +__deps__ := FREETYPE LIBXML2 +$(eval $(call import.MODULE.defs,FONTCONFIG,fontconfig,$(__deps__))) +$(eval $(call import.CONTRIB.defs,FONTCONFIG)) + +FONTCONFIG.FETCH.url = http://download.m0k.org/handbrake/contrib/fontconfig-2.8.0.tar.gz +FONTCONFIG.EXTRACT.tarbase = fontconfig-2.8.0 + +# +# Under MinGW: +# +# - A 'i386-ming32-gcc' $(FONTCONFIG.GCC.gcc) command will be available, +# and the '-arch <arch>' argument should be omitted, as it will confuse this compiler. +# +# - The $(FONTCONFIG.GCC.archs) variable is not set. +# Therefore statically guess the target arch to be i386. +# +ifeq ($(BUILD.system),mingw) + FONTCONFIG.cc_archoption = + FONTCONFIG.config_archoption = --with-arch=i386 +else ifeq ($(BUILD.system),linux) + FONTCONFIG.cc_archoption = +else + FONTCONFIG.cc_archoption = -arch $(FONTCONFIG.GCC.archs) + FONTCONFIG.config_archoption = --with-arch=$(FONTCONFIG.GCC.archs) +endif + +# +# Support cross-compiling: +# +# - Add '-arch <arch>' to CC argument to avoid the need to put a <host_triplet>-gcc +# trampoline script in the PATH, since fontconfig's configure looks for this when +# in cross-compile mode. If such a trampoline were used, it would just call "gcc -arch <arch> $@". +# +# - In the case of MinGW (on i386), a 'i386-ming32-gcc' command will be available, +# and the '-arch <arch>' argument should be omitted, as it will confuse the compiler. +# +# The following line overrides the original line in /make/include/contrib.defs, +# but has the -arch argument added (and '$(1)' presubstituted for 'FONTCONFIG'). +# +FONTCONFIG.CONFIGURE.env.CC = CC="$(FONTCONFIG.GCC.gcc) $(FONTCONFIG.cc_archoption)" + +# +# Support cross-compiling: +# - Remove '-arch <arch>' from *FLAGS variables, since fontconfig's configure script +# needs to be given the freedom to insert that flag as necessary, since there are +# some trampoline executables that need to be built in the native build architecture +# (without the -arch flag). +# +# The following lines override the original lines in /make/include/contrib.defs, +# but have '*archs' removed (and '$(1)' presubstituted for 'FONTCONFIG'). +# +FONTCONFIG.CONFIGURE.env.CFLAGS = CFLAGS="$(call fn.ARGS,FONTCONFIG.GCC,*sysroot *minver ?extra)" +FONTCONFIG.CONFIGURE.env.CXXFLAGS = CXXFLAGS="$(call fn.ARGS,FONTCONFIG.GCC,*sysroot *minver ?extra)" +FONTCONFIG.CONFIGURE.env.CPPFLAGS = CPPFLAGS="$(call fn.ARGS,FONTCONFIG.GCC,*sysroot *minver ?extra)" +FONTCONFIG.CONFIGURE.env.LDFLAGS = LDFLAGS="$(call fn.ARGS,FONTCONFIG.GCC,*sysroot *minver)" + +# +# Force use of libxml2 instead of expat with --enable-libxml2. +# +# Tell configure where to find our (cross-compiled) versions of freetype and libxml2. +# +# Support cross-compiling: +# - Add --with-arch argument since fontconfig's configure isn't smart enough +# to infer it from the --host argument +# +FONTCONFIG.CONFIGURE.extra = \ + --enable-libxml2 \ + --with-freetype-config=$(call fn.ABSOLUTE,$(CONTRIB.build/)bin/freetype-config) \ + LIBXML2_LIBS="-L$(call fn.ABSOLUTE,$(CONTRIB.build/))lib -lxml2" \ + LIBXML2_CFLAGS="-I$(call fn.ABSOLUTE,$(CONTRIB.build/))include/libxml2" \ + $(FONTCONFIG.config_archoption) diff --git a/contrib/fontconfig/module.rules b/contrib/fontconfig/module.rules new file mode 100644 index 000000000..72ebbd965 --- /dev/null +++ b/contrib/fontconfig/module.rules @@ -0,0 +1,2 @@ +$(eval $(call import.MODULE.rules,FONTCONFIG)) +$(eval $(call import.CONTRIB.rules,FONTCONFIG)) diff --git a/contrib/freetype/module.defs b/contrib/freetype/module.defs new file mode 100644 index 000000000..85437bab5 --- /dev/null +++ b/contrib/freetype/module.defs @@ -0,0 +1,5 @@ +$(eval $(call import.MODULE.defs,FREETYPE,freetype)) +$(eval $(call import.CONTRIB.defs,FREETYPE)) + +FREETYPE.FETCH.url = http://download.m0k.org/handbrake/contrib/freetype-2.3.9.tar.gz +FREETYPE.EXTRACT.tarbase = freetype-2.3.9 diff --git a/contrib/freetype/module.rules b/contrib/freetype/module.rules new file mode 100644 index 000000000..d4ebbda30 --- /dev/null +++ b/contrib/freetype/module.rules @@ -0,0 +1,2 @@ +$(eval $(call import.MODULE.rules,FREETYPE)) +$(eval $(call import.CONTRIB.rules,FREETYPE)) diff --git a/contrib/libass/A00-configure.patch b/contrib/libass/A00-configure.patch new file mode 100644 index 000000000..d26e0fb47 --- /dev/null +++ b/contrib/libass/A00-configure.patch @@ -0,0 +1,84 @@ +--- libass-0.9.9/configure 2010-02-28 20:38:16.000000000 -0800 ++++ libass-0.9.9/configure 2010-08-19 23:24:11.000000000 -0700 +@@ -15728,10 +15728,10 @@ + { echo "$as_me:$LINENO: checking for FREETYPE" >&5 + echo $ECHO_N "checking for FREETYPE... $ECHO_C" >&6; } + +-if test -n "$PKG_CONFIG"; then + if test -n "$FREETYPE_CFLAGS"; then + pkg_cv_FREETYPE_CFLAGS="$FREETYPE_CFLAGS" + else ++if test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"freetype2 >= 9.10.3\"") >&5 + ($PKG_CONFIG --exists --print-errors "freetype2 >= 9.10.3") 2>&5 +@@ -15742,14 +15742,14 @@ + else + pkg_failed=yes + fi +- fi + else + pkg_failed=untried + fi +-if test -n "$PKG_CONFIG"; then ++ fi + if test -n "$FREETYPE_LIBS"; then + pkg_cv_FREETYPE_LIBS="$FREETYPE_LIBS" + else ++if test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"freetype2 >= 9.10.3\"") >&5 + ($PKG_CONFIG --exists --print-errors "freetype2 >= 9.10.3") 2>&5 +@@ -15760,10 +15760,10 @@ + else + pkg_failed=yes + fi +- fi + else + pkg_failed=untried + fi ++ fi + + + +@@ -15849,10 +15849,10 @@ + { echo "$as_me:$LINENO: checking for FONTCONFIG" >&5 + echo $ECHO_N "checking for FONTCONFIG... $ECHO_C" >&6; } + +-if test -n "$PKG_CONFIG"; then + if test -n "$FONTCONFIG_CFLAGS"; then + pkg_cv_FONTCONFIG_CFLAGS="$FONTCONFIG_CFLAGS" + else ++if test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"fontconfig >= 2.4.2\"") >&5 + ($PKG_CONFIG --exists --print-errors "fontconfig >= 2.4.2") 2>&5 +@@ -15863,14 +15863,14 @@ + else + pkg_failed=yes + fi +- fi + else + pkg_failed=untried + fi +-if test -n "$PKG_CONFIG"; then ++ fi + if test -n "$FONTCONFIG_LIBS"; then + pkg_cv_FONTCONFIG_LIBS="$FONTCONFIG_LIBS" + else ++if test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"fontconfig >= 2.4.2\"") >&5 + ($PKG_CONFIG --exists --print-errors "fontconfig >= 2.4.2") 2>&5 +@@ -15881,10 +15881,10 @@ + else + pkg_failed=yes + fi +- fi + else + pkg_failed=untried + fi ++ fi + + + diff --git a/contrib/libass/module.defs b/contrib/libass/module.defs new file mode 100644 index 000000000..e5528fd43 --- /dev/null +++ b/contrib/libass/module.defs @@ -0,0 +1,15 @@ +__deps__ := FONTCONFIG FREETYPE +$(eval $(call import.MODULE.defs,LIBASS,libass,$(__deps__))) +$(eval $(call import.CONTRIB.defs,LIBASS)) + +LIBASS.FETCH.url = http://download.m0k.org/handbrake/contrib/libass-0.9.9.tar.bz2 +LIBASS.EXTRACT.tarbase = libass-0.9.9 + +# Disable as many external dependencies as I can get away with +# and tell configure where to find our version of freetype +LIBASS.CONFIGURE.extra = \ + --disable-png --disable-enca \ + FREETYPE_LIBS="-L$(call fn.ABSOLUTE,$(CONTRIB.build/))lib -lfreetype" \ + FREETYPE_CFLAGS="-I$(call fn.ABSOLUTE,$(CONTRIB.build/))include/freetype2" \ + FONTCONFIG_LIBS="-L$(call fn.ABSOLUTE,$(CONTRIB.build/))lib -lfontconfig" \ + FONTCONFIG_CFLAGS="-I$(call fn.ABSOLUTE,$(CONTRIB.build/))include" diff --git a/contrib/libass/module.rules b/contrib/libass/module.rules new file mode 100644 index 000000000..67a5ab679 --- /dev/null +++ b/contrib/libass/module.rules @@ -0,0 +1,2 @@ +$(eval $(call import.MODULE.rules,LIBASS)) +$(eval $(call import.CONTRIB.rules,LIBASS)) diff --git a/contrib/libxml2/module.defs b/contrib/libxml2/module.defs new file mode 100644 index 000000000..519c60887 --- /dev/null +++ b/contrib/libxml2/module.defs @@ -0,0 +1,10 @@ +$(eval $(call import.MODULE.defs,LIBXML2,libxml2)) +$(eval $(call import.CONTRIB.defs,LIBXML2)) + +LIBXML2.FETCH.url = http://download.m0k.org/handbrake/contrib/libxml2-2.7.7.tar.gz +LIBXML2.EXTRACT.tarbase = libxml2-2.7.7 + +# The Python components do not build on MinGW due to the lack of a select() call +# in the MinGW environment. +LIBXML2.CONFIGURE.extra = \ + --without-python
\ No newline at end of file diff --git a/contrib/libxml2/module.rules b/contrib/libxml2/module.rules new file mode 100644 index 000000000..0715628af --- /dev/null +++ b/contrib/libxml2/module.rules @@ -0,0 +1,2 @@ +$(eval $(call import.MODULE.rules,LIBXML2)) +$(eval $(call import.CONTRIB.rules,LIBXML2)) diff --git a/contrib/mp4v2/module.defs b/contrib/mp4v2/module.defs index c27f3470e..a69151df5 100644 --- a/contrib/mp4v2/module.defs +++ b/contrib/mp4v2/module.defs @@ -10,8 +10,5 @@ MP4V2.CONFIGURE.env.CXXFLAGS = CXXFLAGS="$(call fn.ARGS,MP4V2.GCC,*archs *sysroo ## save some build-time by disabling utils MP4V2.CONFIGURE.extra += --disable-util -## make sure gch is disabled; we get build errors on linux with gcc-4.3.x and -g3 -## relatively safe to enable for darwin as it is unlikely to have that bugged version -ifneq (darwin,$(BUILD.system)) - MP4V2.CONFIGURE.extra += --disable-gch -endif +# gch causes build errors with -g3 on many gcc toolchains +MP4V2.CONFIGURE.extra += --disable-gch diff --git a/gtk/src/Makefile.am b/gtk/src/Makefile.am index aec38fcfe..b901baf80 100644 --- a/gtk/src/Makefile.am +++ b/gtk/src/Makefile.am @@ -5,13 +5,13 @@ HB_LIBS= \ -lhb -la52 -lmkv -lavformat -lavcodec -lavutil -lavcore -ldca -ldvdnav -ldvdread \ -lfaac -lmp3lame -lmpeg2 -lvorbis -lvorbisenc -logg -lsamplerate \ -lx264 -lmp4v2 -lswscale -ltheora -lfaad -lz \ - -lbz2 -liberty -lpthreadGC2 -lbluray + -lbz2 -liberty -lpthreadGC2 -lbluray -lass -lfontconfig -lfreetype else HB_LIBS= \ -lhb -la52 -lmkv -lavformat -lavcodec -lavutil -lavcore -ldca -ldvdnav -ldvdread \ -lfaac -lmp3lame -lmpeg2 -lvorbis -lvorbisenc -logg -lsamplerate \ -lx264 -lmp4v2 -lswscale -ltheora -lfaad -lz \ - -lbz2 -lpthread -lbluray + -lbz2 -lpthread -lbluray -lass -lfontconfig -lfreetype endif icons = \ diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 8ebdd1d17..3683c23e5 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -2187,20 +2187,9 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) for (ii = 0; ii < count; ii++) { subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii); - // Skip subtitles that must be burned if there is already - // a burned subtitle in the list -#if 0 - if (subtitle->source == VOBSUB) - { - options[ii] = g_strdup_printf("%d - %s", ii+1, subtitle->lang); - } - else -#endif - { - options[ii] = g_strdup_printf("%d - %s (%s)", ii+1, - subtitle->lang, - ghb_subtitle_source_name(subtitle->source)); - } + options[ii] = g_strdup_printf("%d - %s (%s)", ii+1, + subtitle->lang, + ghb_subtitle_source_name(subtitle->source)); subtitle_opts.map[ii+1].option = options[ii]; subtitle_opts.map[ii+1].shortOpt = index_str[ii]; subtitle_opts.map[ii+1].ivalue = ii; @@ -2575,6 +2564,18 @@ ghb_find_cc_track(gint titleindex) return -2; } +static gboolean +canForce(int source) +{ + return (source == VOBSUB); +} + +static gboolean +canBurn(int source) +{ + return (source == VOBSUB || source == SSASUB); +} + gint ghb_find_subtitle_track( gint titleindex, @@ -2627,7 +2628,8 @@ ghb_find_subtitle_track( continue; subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii ); - if ((!(burn || force) || (subtitle->source == VOBSUB)) && + if (((!force || (force && canForce(subtitle->source))) && + (!burn || (burn && canBurn(subtitle->source)))) && ((strcmp(lang, subtitle->iso639_2) == 0) || (strcmp(lang, "und") == 0))) { @@ -4878,15 +4880,16 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) if (subt != NULL) { sub_config = subt->config; - if (!burned && subt->format == PICTURESUB) + if (!burned) { sub_config.dest = PASSTHRUSUB; } - else if ( burned && subt->format == PICTURESUB ) + else if ( burned && canBurn(subt->source) ) { // Only allow one subtitle to be burned into the video if (one_burned) continue; + sub_config.dest = RENDERSUB; one_burned = TRUE; } sub_config.force = force; diff --git a/gtk/src/subtitlehandler.c b/gtk/src/subtitlehandler.c index a7f06712a..63b2f20b4 100644 --- a/gtk/src/subtitlehandler.c +++ b/gtk/src/subtitlehandler.c @@ -44,6 +44,18 @@ mustBurn(signal_user_data_t *ud, GValue *settings) return FALSE; } +static gboolean +canBurn(int source) +{ + return (source == VOBSUB || source == SSASUB); +} + +static gboolean +canForce(int source) +{ + return (source == VOBSUB); +} + gboolean ghb_soft_in_subtitle_list(GValue *subtitle_list) { @@ -519,7 +531,7 @@ subtitle_forced_toggled_cb( settings = ghb_array_get_nth(subtitle_list, row); source = ghb_settings_get_int(settings, "SubtitleSource"); - if (source != VOBSUB) + if (!canForce(source)) return; ghb_settings_set_boolean(settings, "SubtitleForced", active); @@ -567,7 +579,7 @@ subtitle_burned_toggled_cb( settings = ghb_array_get_nth(subtitle_list, row); source = ghb_settings_get_int(settings, "SubtitleSource"); - if (source != VOBSUB) + if (!canBurn(source)) return; if (!active && mustBurn(ud, settings)) return; @@ -654,7 +666,8 @@ subtitle_list_refresh_selected(signal_user_data_t *ud) gint row; GValue *settings = NULL; const GValue *subtitle_list; - gboolean allow_burn_force = FALSE; + gboolean allow_force = FALSE; + gboolean allow_burn = FALSE; g_debug("subtitle_list_refresh_selected ()"); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); @@ -681,14 +694,17 @@ subtitle_list_refresh_selected(signal_user_data_t *ud) gint i_source; i_source = ghb_settings_get_int(settings, "SubtitleSource"); - if (i_source != VOBSUB) + if (!canBurn(i_source)) { - // Force and burn only apply to VOBSUBS - forced = FALSE; burned = FALSE; - ghb_settings_set_boolean(settings, "SubtitleForced", forced); ghb_settings_set_boolean(settings, "SubtitleBurned", burned); } + if (!canForce(i_source)) + { + // Force only apply to VOBSUBS + forced = FALSE; + ghb_settings_set_boolean(settings, "SubtitleForced", forced); + } if (i_source == SRTSUB) { @@ -730,9 +746,10 @@ subtitle_list_refresh_selected(signal_user_data_t *ud) burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); } - if (i_source == VOBSUB) - allow_burn_force = TRUE; - + if (canBurn(i_source)) + allow_burn = TRUE; + if (canForce(i_source)) + allow_force = TRUE; gtk_list_store_set(GTK_LIST_STORE(store), &iter, // These are displayed in list @@ -744,8 +761,8 @@ subtitle_list_refresh_selected(signal_user_data_t *ud) // These are used to set combo box values when a list item is selected 5, s_track, 6, i_source, - 7, allow_burn_force, - 8, allow_burn_force, + 7, allow_force, + 8, allow_burn, -1); g_free(track); g_free(source); @@ -892,7 +909,8 @@ add_to_subtitle_list( gboolean forced, burned, def; gchar *s_track; gint i_source; - gboolean allow_burn_force = FALSE; + gboolean allow_force = FALSE; + gboolean allow_burn = FALSE; g_debug("add_to_subtitle_list ()"); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); @@ -908,8 +926,10 @@ add_to_subtitle_list( i_source = ghb_settings_get_int(settings, "SubtitleSource"); source = ghb_subtitle_source_name(i_source); - if (i_source == VOBSUB) - allow_burn_force = TRUE; + if (canBurn(i_source)) + allow_burn = TRUE; + if (canForce(i_source)) + allow_force = TRUE; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, @@ -921,8 +941,8 @@ add_to_subtitle_list( // These are used to set combo box values when a list item is selected 5, s_track, 6, i_source, - 7, allow_burn_force, - 8, allow_burn_force, + 7, allow_force, + 8, allow_burn, 9, FALSE, -1); gtk_tree_selection_select_iter(selection, &iter); diff --git a/libhb/common.c b/libhb/common.c index f7b9ee384..35417cb6c 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -730,6 +730,7 @@ hb_title_t * hb_title_init( char * path, int index ) t->list_audio = hb_list_init(); t->list_chapter = hb_list_init(); t->list_subtitle = hb_list_init(); + t->list_attachment = hb_list_init(); strcat( t->path, path ); // default to decoding mpeg2 t->video_id = 0xE0; @@ -749,6 +750,7 @@ void hb_title_close( hb_title_t ** _t ) hb_audio_t * audio; hb_chapter_t * chapter; hb_subtitle_t * subtitle; + hb_attachment_t * attachment; while( ( audio = hb_list_item( t->list_audio, 0 ) ) ) { @@ -767,9 +769,31 @@ void hb_title_close( hb_title_t ** _t ) while( ( subtitle = hb_list_item( t->list_subtitle, 0 ) ) ) { hb_list_rem( t->list_subtitle, subtitle ); + if ( subtitle->extradata ) + { + free( subtitle->extradata ); + subtitle->extradata = NULL; + } free( subtitle ); } hb_list_close( &t->list_subtitle ); + + while( ( attachment = hb_list_item( t->list_attachment, 0 ) ) ) + { + hb_list_rem( t->list_attachment, attachment ); + if ( attachment->name ) + { + free( attachment->name ); + attachment->name = NULL; + } + if ( attachment->data ) + { + free( attachment->data ); + attachment->data = NULL; + } + free( attachment ); + } + hb_list_close( &t->list_attachment ); if( t->metadata ) { @@ -924,6 +948,11 @@ hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src) { subtitle = calloc(1, sizeof(*subtitle)); memcpy(subtitle, src, sizeof(*subtitle)); + if ( src->extradata ) + { + subtitle->extradata = malloc( src->extradata_size ); + memcpy( subtitle->extradata, src->extradata, src->extradata_size ); + } } return subtitle; } @@ -1022,6 +1051,32 @@ char * hb_strdup_printf( char * fmt, ... ) } /********************************************************************** + * hb_attachment_copy + ********************************************************************** + * + *********************************************************************/ +hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src) +{ + hb_attachment_t *attachment = NULL; + + if( src ) + { + attachment = calloc(1, sizeof(*attachment)); + memcpy(attachment, src, sizeof(*attachment)); + if ( src->name ) + { + attachment->name = strdup( src->name ); + } + if ( src->data ) + { + attachment->data = malloc( src->size ); + memcpy( attachment->data, src->data, src->size ); + } + } + return attachment; +} + +/********************************************************************** * hb_yuv2rgb ********************************************************************** * Converts a YCbCr pixel to an RGB pixel. @@ -1089,3 +1144,26 @@ int hb_rgb2yuv(int rgb) return (y << 16) | (Cb << 8) | Cr; } +const char * hb_subsource_name( int source ) +{ + switch (source) + { + case VOBSUB: + return "VOBSUB"; + case SRTSUB: + return "SRT"; + case CC608SUB: + return "CC"; + case CC708SUB: + return "CC"; + case UTF8SUB: + return "UTF-8"; + case TX3GSUB: + return "TX3G"; + case SSASUB: + return "SSA"; + default: + return "Unknown"; + } +} + diff --git a/libhb/common.h b/libhb/common.h index b59cba515..bba48350c 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -63,6 +63,7 @@ typedef struct hb_audio_s hb_audio_t; typedef struct hb_audio_config_s hb_audio_config_t; typedef struct hb_subtitle_s hb_subtitle_t; typedef struct hb_subtitle_config_s hb_subtitle_config_t; +typedef struct hb_attachment_s hb_attachment_t; typedef struct hb_metadata_s hb_metadata_t; typedef struct hb_state_s hb_state_t; typedef union hb_esconfig_u hb_esconfig_t; @@ -102,10 +103,12 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg); int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg); hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i); +hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src); int hb_subtitle_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, int track); int hb_srt_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, const char *lang); +hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src); struct hb_rate_s { @@ -194,8 +197,8 @@ struct hb_job_s int itu_par; int par_width; int par_height; - int dar_width; - int dar_height; + int dar_width; // 0 if normal + int dar_height; // 0 if normal int keep_display_aspect; } anamorphic; @@ -237,8 +240,7 @@ struct hb_job_s /* List of audio settings. */ hb_list_t * list_audio; - /* Subtitles - */ + /* Subtitles */ hb_list_t * list_subtitle; /* Muxer settings @@ -488,9 +490,8 @@ struct hb_chapter_s * > config.dest * - whether to render the subtitle on the video track (RENDERSUB) or * to pass it through its own subtitle track in the output container (PASSTHRUSUB) - * - for legacy compatibility, all newly created VOBSUB tracks should default to RENDERSUB - * - since only VOBSUBs are renderable (as of 2010-04-25), all other newly created - * subtitle track types should default to PASSTHRUSUB + * - all newly created non-VOBSUB tracks should default to PASSTHRUSUB + * - all newly created VOBSUB tracks should default to RENDERSUB, for legacy compatibility * > lang * - user-readable description of the subtitle track * - may correspond to the language of the track (see the 'iso639_2' field) @@ -516,6 +517,10 @@ struct hb_subtitle_s uint32_t palette[16]; int width; int height; + + // Codec private data for subtitles originating from FFMPEG sources + uint8_t * extradata; + int extradata_size; int hits; /* How many hits/occurrences of this subtitle */ int forced_hits; /* How many forced hits in this subtitle */ @@ -530,6 +535,19 @@ struct hb_subtitle_s #endif }; +/* + * An attachment. + * + * These are usually used for attaching embedded fonts to movies containing SSA subtitles. + */ +struct hb_attachment_s +{ + enum attachtype { FONT_TTF_ATTACH } type; + char * name; + char * data; + int size; +}; + struct hb_metadata_s { char name[255]; @@ -593,6 +611,7 @@ struct hb_title_s hb_list_t * list_chapter; hb_list_t * list_audio; hb_list_t * list_subtitle; + hb_list_t * list_attachment; /* Job template for this title */ hb_job_t * job; @@ -800,4 +819,6 @@ char * hb_strdup_printf( char * fmt, ... ); int hb_yuv2rgb(int yuv); int hb_rgb2yuv(int rgb); +const char * hb_subsource_name( int source ); + #endif diff --git a/libhb/decssasub.c b/libhb/decssasub.c index 2b350dc47..99e4259a0 100644 --- a/libhb/decssasub.c +++ b/libhb/decssasub.c @@ -4,13 +4,19 @@ It may be used under the terms of the GNU General Public License. */ /* - * Converts SSA subtitles to UTF-8 subtitles with limited HTML-style markup (<b>, <i>, <u>). + * Converts SSA subtitles to either: + * (1) TEXTSUB format: UTF-8 subtitles with limited HTML-style markup (<b>, <i>, <u>), or + * (2) PICTURESUB format, using libass. * * SSA format references: * http://www.matroska.org/technical/specs/subtitles/ssa.html * http://moodub.free.fr/video/ass-specs.doc * vlc-1.0.4/modules/codec/subtitles/subsass.c:ParseSSAString * + * libass references: + * libass-0.9.9/ass.h + * vlc-1.0.4/modules/codec/libass.c + * * @author David Foster (davidfstr) */ @@ -18,6 +24,17 @@ #include <stdio.h> #include "hb.h" +#include <ass/ass.h> + +struct hb_work_private_s +{ + // If decoding to PICTURESUB format: + ASS_Library *ssa; + ASS_Renderer *renderer; + ASS_Track *ssaTrack; + int readOrder; +}; + typedef enum { BOLD = 0x01, ITALIC = 0x02, @@ -92,14 +109,17 @@ static void ssa_append_html_tags_for_style_change( #undef APPEND } -static hb_buffer_t *ssa_decode_to_utf8_line( uint8_t *in_data, int in_size ); +static hb_buffer_t *ssa_decode_line_to_utf8( uint8_t *in_data, int in_size, int in_sequence ); +static hb_buffer_t *ssa_decode_line_to_picture( hb_work_object_t * w, uint8_t *in_data, int in_size, int in_sequence ); /* + * Decodes a single SSA packet to one or more TEXTSUB or PICTURESUB subtitle packets. + * * SSA packet format: * ( Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text CR LF ) + * 1 2 3 4 5 6 7 8 9 10 */ -static hb_buffer_t *ssa_decode_to_utf8( hb_buffer_t *in ) +static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in ) { // Store NULL after the end of the buffer to make using string processing safe hb_buffer_realloc( in, in->size + 1 ); @@ -119,22 +139,31 @@ static hb_buffer_t *ssa_decode_to_utf8( hb_buffer_t *in ) continue; // Decode an individual SSA line - hb_buffer_t *out = ssa_decode_to_utf8_line( (uint8_t*)curLine, strlen( curLine ) ); - - // We shouldn't be storing the extra NULL character, - // but the MP4 muxer expects this, unfortunately. - if ( out->size > 0 && out->data[out->size - 1] != '\0' ) { - // NOTE: out->size remains unchanged - hb_buffer_realloc( out, out->size + 1 ); - out->data[out->size] = '\0'; - } - - // If the input packet was non-empty, do not pass through - // an empty output packet (even if the subtitle was empty), - // as this would be interpreted as an end-of-stream - if ( in->size > 0 && out->size == 0 ) { - hb_buffer_close(&out); - continue; + hb_buffer_t *out; + if ( w->subtitle->config.dest == PASSTHRUSUB ) { + out = ssa_decode_line_to_utf8( (uint8_t *) curLine, strlen( curLine ), in->sequence ); + if ( out == NULL ) + continue; + + // We shouldn't be storing the extra NULL character, + // but the MP4 muxer expects this, unfortunately. + if ( out->size > 0 && out->data[out->size - 1] != '\0' ) { + // NOTE: out->size remains unchanged + hb_buffer_realloc( out, out->size + 1 ); + out->data[out->size] = '\0'; + } + + // If the input packet was non-empty, do not pass through + // an empty output packet (even if the subtitle was empty), + // as this would be interpreted as an end-of-stream + if ( in->size > 0 && out->size == 0 ) { + hb_buffer_close(&out); + continue; + } + } else if ( w->subtitle->config.dest == RENDERSUB ) { + out = ssa_decode_line_to_picture( w, (uint8_t *) curLine, strlen( curLine ), in->sequence ); + if ( out == NULL ) + continue; } // Append 'out' to 'out_list' @@ -146,50 +175,68 @@ static hb_buffer_t *ssa_decode_to_utf8( hb_buffer_t *in ) } /* - * SSA line format: - * Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text '\0' - * 1 2 3 4 5 6 7 8 9 10 + * Parses the start and stop time from the specified SSA packet. + * + * Returns true if parsing failed; false otherwise. */ -static hb_buffer_t *ssa_decode_to_utf8_line( uint8_t *in_data, int in_size ) +static int parse_timing_from_ssa_packet( char *in_data, int64_t *in_start, int64_t *in_stop ) { - uint8_t *pos = in_data; - uint8_t *end = in_data + in_size; - /* * Parse Start and End fields for timing information */ int start_hr, start_min, start_sec, start_centi; int end_hr, end_min, end_sec, end_centi; - int numPartsRead = sscanf( (char *) in_data, "%*128[^,]," + int numPartsRead = sscanf( (char *) in_data, "Dialogue: %*128[^,]," "%d:%d:%d.%d," // Start "%d:%d:%d.%d,", // End &start_hr, &start_min, &start_sec, &start_centi, &end_hr, &end_min, &end_sec, &end_centi ); if ( numPartsRead != 8 ) - goto fail; + return 1; - int64_t in_start = SSA_2_HB_TIME(start_hr, start_min, start_sec, start_centi); - int64_t in_stop = SSA_2_HB_TIME( end_hr, end_min, end_sec, end_centi); + *in_start = SSA_2_HB_TIME(start_hr, start_min, start_sec, start_centi); + *in_stop = SSA_2_HB_TIME( end_hr, end_min, end_sec, end_centi); - /* - * Advance 'pos' to the beginning of the Text field - */ + return 0; +} + +static uint8_t *find_field( uint8_t *pos, uint8_t *end, int fieldNum ) +{ int curFieldID = 1; while (pos < end) { if ( *pos++ == ',' ) { curFieldID++; - if ( curFieldID == 10 ) // Text - break; + if ( curFieldID == fieldNum ) + return pos; } } - if ( curFieldID != 10 ) + return NULL; +} + +/* + * SSA line format: + * Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text '\0' + * 1 2 3 4 5 6 7 8 9 10 + */ +static hb_buffer_t *ssa_decode_line_to_utf8( uint8_t *in_data, int in_size, int in_sequence ) +{ + uint8_t *pos = in_data; + uint8_t *end = in_data + in_size; + + // Parse values for in->start and in->stop + int64_t in_start, in_stop; + if ( parse_timing_from_ssa_packet( (char *) in_data, &in_start, &in_stop ) ) + goto fail; + + uint8_t *textFieldPos = find_field( pos, end, 10 ); + if ( textFieldPos == NULL ) goto fail; - uint8_t *textFieldPos = pos; // Count the number of style overrides in the Text field int numStyleOverrides = 0; + pos = textFieldPos; while ( pos < end ) { if (*pos++ == '{') @@ -207,7 +254,7 @@ static hb_buffer_t *ssa_decode_to_utf8_line( uint8_t *in_data, int in_size ) * The Text field contains plain text marked up with: * (1) '\n' -> space * (2) '\N' -> newline - * (3) curly-brace control codes like '{\k44}' -> empty (strip them) + * (3) curly-brace control codes like '{\k44}' -> HTML tags / strip * * Perform the above conversions and copy it to the output packet */ @@ -253,6 +300,7 @@ static hb_buffer_t *ssa_decode_to_utf8_line( uint8_t *in_data, int in_size ) // Copy metadata from the input packet to the output packet out->start = in_start; out->stop = in_stop; + out->sequence = in_sequence; return out; @@ -261,8 +309,252 @@ fail: return NULL; } +/* + * SSA line format: + * Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text '\0' + * 1 2 3 4 5 6 7 8 9 10 + * + * MKV-SSA packet format: + * ReadOrder,Marked, Style,Name,MarginL,MarginR,MarginV,Effect,Text '\0' + * 1 2 3 4 5 6 7 8 9 + */ +static hb_buffer_t *ssa_decode_line_to_picture( hb_work_object_t * w, uint8_t *in_data, int in_size, int in_sequence ) +{ + hb_work_private_t * pv = w->private_data; + + // Parse values for in->start and in->stop + int64_t in_start, in_stop; + if ( parse_timing_from_ssa_packet( (char *) in_data, &in_start, &in_stop ) ) + goto fail; + + // Convert the SSA packet to MKV-SSA format, which is what libass expects + char *mkvIn; + int mkvInSize; + { + char *layerField = malloc( in_size ); + int numPartsRead = sscanf( (char *) in_data, "Dialogue: %128[^,],", layerField ); + if ( numPartsRead != 1 ) + goto fail; + + char *styleToTextFields = (char *) find_field( in_data, in_data + in_size, 4 ); + if ( styleToTextFields == NULL ) { + free( layerField ); + goto fail; + } + + mkvIn = malloc( in_size + 1 ); + mkvIn[0] = '\0'; + sprintf(mkvIn, "%d", pv->readOrder++); // ReadOrder: make this up + strcat( mkvIn, "," ); + strcat( mkvIn, layerField ); + strcat( mkvIn, "," ); + strcat( mkvIn, (char *) styleToTextFields ); + + mkvInSize = strlen(mkvIn); + + free( layerField ); + } + + // Parse MKV-SSA packet + ass_process_chunk( pv->ssaTrack, mkvIn, mkvInSize, in_start / 90, (in_stop - in_start) / 90 ); + + free( mkvIn ); + + // TODO: To support things like karaoke, it won't be sufficient to only generate + // new subtitle pictures when there are subtitle packets. Rather, pictures will + // need to be generated potentially continuously. + // + // Until "karaoke support" is implemented, make an educated guess about the + // timepoint within the subtitle that should be rendered. I guess the midpoint. + int64_t renderTime = ( in_start + in_stop ) / 2; + + int changed; + ASS_Image *frameList = ass_render_frame( pv->renderer, pv->ssaTrack, renderTime / 90, &changed ); + if ( !changed && !frameList ) + return NULL; + + int numFrames = 0; + ASS_Image *curFrame; + for (curFrame = frameList; curFrame; curFrame = curFrame->next) + numFrames++; + + hb_buffer_t *outSubpictureList = NULL; + hb_buffer_t **outSubpictureListTailPtr = &outSubpictureList; + + // Generate a PICTURESUB packet from the frames + ASS_Image *frame; + for (frame = frameList; frame; frame = frame->next) { + // Allocate pixmap where drawing will be done + uint8_t *rgba = calloc(frame->w * frame->h * 4, 1); + + unsigned r = (frame->color >> 24) & 0xff; + unsigned g = (frame->color >> 16) & 0xff; + unsigned b = (frame->color >> 8) & 0xff; + unsigned a = (frame->color ) & 0xff; + + int x, y; + for (y = 0; y < frame->h; y++) { + for (x = 0; x < frame->w; x++) { + unsigned srcAlphaPrenormalized = frame->bitmap[y*frame->stride + x]; + unsigned srcAlpha = (255 - a) * srcAlphaPrenormalized / 255; + + uint8_t *dst = &rgba[(y*frame->w + x) * 4]; + unsigned oldDstAlpha = dst[3]; + + if (oldDstAlpha == 0) { + // Optimized version + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = srcAlpha; + } else { + dst[3] = 255 - ( 255 - dst[3] ) * ( 255 - srcAlpha ) / 255; + if (dst[3] != 0) { + dst[0] = ( dst[0] * oldDstAlpha * (255-srcAlpha) / 255 + r * srcAlpha ) / dst[3]; + dst[1] = ( dst[1] * oldDstAlpha * (255-srcAlpha) / 255 + g * srcAlpha ) / dst[3]; + dst[2] = ( dst[2] * oldDstAlpha * (255-srcAlpha) / 255 + b * srcAlpha ) / dst[3]; + } + } + } + } + + // Generate output subpicture (in PICTURESUB format) + hb_buffer_t *out = hb_buffer_init(frame->w * frame->h * 4); + out->x = frame->dst_x; + out->y = frame->dst_y; + out->width = frame->w; + out->height = frame->h; + + int i; + int numPixels = frame->w * frame->h; + for (i = 0; i < numPixels; i++) { + uint8_t *srcRgba = &rgba[i * 4]; + + uint8_t *dstY = &out->data[(numPixels * 0) + i]; + uint8_t *dstA = &out->data[(numPixels * 1) + i]; + uint8_t *dstU = &out->data[(numPixels * 2) + i]; + uint8_t *dstV = &out->data[(numPixels * 3) + i]; + + int srcYuv = hb_rgb2yuv((srcRgba[0] << 16) | (srcRgba[1] << 8) | (srcRgba[2] << 0)); + int srcA = srcRgba[3]; + + *dstY = (srcYuv >> 16) & 0xff; + *dstU = (srcYuv >> 8 ) & 0xff; + *dstV = (srcYuv >> 0 ) & 0xff; + *dstA = srcA / 16; // HB's max alpha value is 16 + } + + free(rgba); + + *outSubpictureListTailPtr = out; + outSubpictureListTailPtr = &out->next_subpicture; + } + + // NOTE: The subpicture list is actually considered a single packet by most other code + hb_buffer_t *out = outSubpictureList; + + // Copy metadata from the input packet to the output packet + out->start = in_start; + out->stop = in_stop; + out->sequence = in_sequence; + + return out; + +fail: + hb_log( "decssasub: malformed SSA subtitle packet: %.*s\n", in_size, in_data ); + return NULL; +} + +static void ssa_log(int level, const char *fmt, va_list args, void *data) +{ + if ( level < 5 ) // same as default verbosity when no callback is set + { + char *msg; + if ( vasprintf( &msg, fmt, args ) < 0 ) + { + hb_log( "decssasub: could not report libass message\n" ); + return; + } + hb_log( "[ass] %s", msg ); // no need for extra '\n' because libass sends it + + free( msg ); + } +} + static int decssaInit( hb_work_object_t * w, hb_job_t * job ) { + hb_work_private_t * pv; + + pv = calloc( 1, sizeof( hb_work_private_t ) ); + w->private_data = pv; + + if ( w->subtitle->config.dest == RENDERSUB ) { + pv->ssa = ass_library_init(); + if ( !pv->ssa ) { + hb_log( "decssasub: libass initialization failed\n" ); + return 1; + } + + // Redirect libass output to hb_log + ass_set_message_cb( pv->ssa, ssa_log, NULL ); + + // Load embedded fonts + hb_list_t * list_attachment = job->title->list_attachment; + int i; + for ( i = 0; i < hb_list_count(list_attachment); i++ ) + { + hb_attachment_t * attachment = hb_list_item( list_attachment, i ); + + if ( attachment->type == FONT_TTF_ATTACH ) + { + ass_add_font( + pv->ssa, + attachment->name, + attachment->data, + attachment->size ); + } + } + + ass_set_extract_fonts( pv->ssa, 1 ); + ass_set_style_overrides( pv->ssa, NULL ); + + pv->renderer = ass_renderer_init( pv->ssa ); + if ( !pv->renderer ) { + hb_log( "decssasub: renderer initialization failed\n" ); + return 1; + } + + ass_set_use_margins( pv->renderer, 0 ); + ass_set_hinting( pv->renderer, ASS_HINTING_LIGHT ); // VLC 1.0.4 uses this + ass_set_font_scale( pv->renderer, 1.0 ); + ass_set_line_spacing( pv->renderer, 1.0 ); + + // Setup default font family + // + // SSA v4.00 requires that "Arial" be the default font + const char *font = NULL; + const char *family = "Arial"; + // NOTE: This can sometimes block for several *seconds*. + // It seems that process_fontdata() for some embedded fonts is slow. + ass_set_fonts( pv->renderer, font, family, /*haveFontConfig=*/1, NULL, 1 ); + + // Setup track state + pv->ssaTrack = ass_new_track( pv->ssa ); + if ( !pv->ssaTrack ) { + hb_log( "decssasub: ssa track initialization failed\n" ); + return 1; + } + + // NOTE: The codec extradata is expected to be in MKV format + ass_process_codec_private( pv->ssaTrack, + (char *) w->subtitle->extradata, w->subtitle->extradata_size ); + + int originalWidth = job->title->width; + int originalHeight = job->title->height; + ass_set_frame_size( pv->renderer, originalWidth, originalHeight); + ass_set_aspect_ratio( pv->renderer, /*dar=*/1.0, /*sar=*/1.0 ); + } + return 0; } @@ -273,7 +565,7 @@ static int decssaWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t * out_list = NULL; if ( in->size > 0 ) { - out_list = ssa_decode_to_utf8(in); + out_list = ssa_decode_packet(w, in); } else { out_list = hb_buffer_init( 0 ); } @@ -288,7 +580,16 @@ static int decssaWork( hb_work_object_t * w, hb_buffer_t ** buf_in, static void decssaClose( hb_work_object_t * w ) { - // nothing + hb_work_private_t * pv = w->private_data; + + if ( pv->ssaTrack ) + ass_free_track( pv->ssaTrack ); + if ( pv->renderer ) + ass_renderer_done( pv->renderer ); + if ( pv->ssa ) + ass_library_done( pv->ssa ); + + free( w->private_data ); } hb_work_object_t hb_decssasub = diff --git a/libhb/decvobsub.c b/libhb/decvobsub.c index 3b5177ca3..fc4a9e24f 100644 --- a/libhb/decvobsub.c +++ b/libhb/decvobsub.c @@ -17,10 +17,10 @@ * * Output format of this decoder is PICTURESUB, which is: * struct PictureSubPacket { - * uint8_t lum[pixelCount]; - * uint8_t alpha[pixelCount]; - * uint8_t chromaU[pixelCount]; - * uint8_t chromaV[pixelCount]; + * uint8_t lum[pixelCount]; // Y + * uint8_t alpha[pixelCount]; // alpha (max = 16) + * uint8_t chromaU[pixelCount]; // Cb + * uint8_t chromaV[pixelCount]; // Cr * } */ diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index 22eb286d5..5ae5a3929 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -235,13 +235,22 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, // doesn't do the trick. It must be set in the AVFrame. frame->quality = pv->context->global_quality; - /* Should be way too large */ - buf = hb_video_buffer_init( job->width, job->height ); - buf->size = avcodec_encode_video( pv->context, buf->data, buf->alloc, - frame ); - buf->start = in->start; - buf->stop = in->stop; - buf->frametype = pv->context->coded_frame->key_frame ? HB_FRAME_KEY : HB_FRAME_REF; + if ( pv->context->codec ) + { + /* Should be way too large */ + buf = hb_video_buffer_init( job->width, job->height ); + buf->size = avcodec_encode_video( pv->context, buf->data, buf->alloc, + frame ); + buf->start = in->start; + buf->stop = in->stop; + buf->frametype = pv->context->coded_frame->key_frame ? HB_FRAME_KEY : HB_FRAME_REF; + } + else + { + buf = NULL; + + hb_error( "encavcodec: codec context has uninitialized codec; skipping frame" ); + } av_free( frame ); diff --git a/libhb/hb.c b/libhb/hb.c index 11b80357e..36fcd75c9 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -1225,6 +1225,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) hb_chapter_t * chapter, * chapter_copy; hb_audio_t * audio; hb_subtitle_t * subtitle, * subtitle_copy; + hb_attachment_t * attachment; int i; char audio_lang[4]; @@ -1272,7 +1273,6 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) /* Copy the audio track(s) we want */ title_copy->list_audio = hb_list_init(); - for( i = 0; i < hb_list_count(job->list_audio); i++ ) { if( ( audio = hb_list_item( job->list_audio, i ) ) ) @@ -1281,7 +1281,18 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) } } + /* Initialize subtitle list - filled out further below */ title_copy->list_subtitle = hb_list_init(); + + /* Copy all the attachments */ + title_copy->list_attachment = hb_list_init(); + for( i = 0; i < hb_list_count(title->list_attachment); i++ ) + { + if( ( attachment = hb_list_item( title->list_attachment, i ) ) ) + { + hb_list_add( title_copy->list_attachment, hb_attachment_copy(attachment) ); + } + } /* * The following code is confusing, there are two ways in which diff --git a/libhb/internal.h b/libhb/internal.h index fe1cdca26..30bf022d5 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -85,15 +85,16 @@ struct hb_buffer_s /* Holds the output PTS from x264, for use by b-frame offsets in muxmp4.c */ int64_t renderOffset; - // VOB subtitle packets: + // PICTURESUB subtitle packets: // Location and size of the subpicture. int x; int y; int width; int height; + hb_buffer_t * next_subpicture; // Video packets (after processing by the hb_sync_video work-object): - // A (copy of a) VOB subtitle packet that needs to be burned into this video packet by the hb_render work-object. + // A (copy of a) PICTURESUB subtitle packet that needs to be burned into this video packet by the hb_render work-object. // Subtitles that are simply passed thru are NOT attached to the associated video packets. hb_buffer_t * sub; diff --git a/libhb/module.defs b/libhb/module.defs index c6fb9dceb..4759a921a 100644 --- a/libhb/module.defs +++ b/libhb/module.defs @@ -1,5 +1,5 @@ -__deps__ := A52DEC BZIP2 FAAC FAAD2 FFMPEG LAME LIBDCA \ - LIBDVDREAD LIBDVDNAV LIBICONV LIBMKV LIBOGG LIBSAMPLERATE LIBTHEORA LIBVORBIS \ +__deps__ := A52DEC BZIP2 FAAC FAAD2 FFMPEG FONTCONFIG FREETYPE LAME LIBASS LIBDCA \ + LIBDVDREAD LIBDVDNAV LIBICONV LIBMKV LIBOGG LIBSAMPLERATE LIBTHEORA LIBVORBIS LIBXML2 \ MP4V2 MPEG2DEC PTHREADW32 X264 ZLIB LIBBLURAY $(eval $(call import.MODULE.defs,LIBHB,libhb,$(__deps__))) @@ -89,8 +89,8 @@ LIBHB.dll = $(LIBHB.build/)hb.dll LIBHB.lib = $(LIBHB.build/)hb.lib LIBHB.dll.libs = $(foreach n, \ - a52 avcore avcodec avformat avutil dca dvdnav dvdread faac faad mkv mpeg2 mp3lame mp4v2 \ - ogg samplerate swscale theora vorbis vorbisenc x264 bluray, \ + a52 ass avcore avcodec avformat avutil dca dvdnav dvdread faac faad fontconfig freetype mkv mpeg2 mp3lame mp4v2 \ + ogg samplerate swscale theora vorbis vorbisenc x264 xml2 bluray, \ $(CONTRIB.build/)lib/lib$(n).a ) ifneq ($(HAS.iconv),1) diff --git a/libhb/render.c b/libhb/render.c index 6888a1e0a..98bc7fea3 100644 --- a/libhb/render.c +++ b/libhb/render.c @@ -472,8 +472,14 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, pv->dropped_frames++; /* Pop the frame's subtitle and dispose of it. */ - hb_buffer_t * subtitles = hb_fifo_get( pv->subtitle_queue ); - hb_buffer_close( &subtitles ); + hb_buffer_t * subpicture_list = hb_fifo_get( pv->subtitle_queue ); + hb_buffer_t * subpicture; + hb_buffer_t * subpicture_next; + for ( subpicture = subpicture_list; subpicture; subpicture = subpicture_next ) + { + subpicture_next = subpicture->next_subpicture; + hb_buffer_close( &subpicture ); + } buf_tmp_in = NULL; break; } @@ -500,10 +506,13 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, /* Apply subtitles */ if( buf_tmp_in ) { - hb_buffer_t * subtitles = hb_fifo_get( pv->subtitle_queue ); - if( subtitles ) + hb_buffer_t * subpicture_list = hb_fifo_get( pv->subtitle_queue ); + hb_buffer_t * subpicture; + hb_buffer_t * subpicture_next; + for ( subpicture = subpicture_list; subpicture; subpicture = subpicture_next ) { - ApplySub( job, buf_tmp_in, &subtitles ); + subpicture_next = subpicture->next_subpicture; + ApplySub( job, buf_tmp_in, &subpicture ); } } diff --git a/libhb/stream.c b/libhb/stream.c index 58b2506f0..85a891c7b 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -3181,9 +3181,55 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id strcpy( subtitle->lang, language->eng_name ); strncpy( subtitle->iso639_2, language->iso639_2, 4 ); + // Copy the extradata for the subtitle track + subtitle->extradata = malloc( codec->extradata_size ); + memcpy( subtitle->extradata, codec->extradata, codec->extradata_size ); + subtitle->extradata_size = codec->extradata_size; + hb_list_add(title->list_subtitle, subtitle); } +static char *get_ffmpeg_metadata_value( AVMetadata *m, char *key ) +{ + AVMetadataTag *tag = NULL; + while ( tag = av_metadata_get(m, "", tag, AV_METADATA_IGNORE_SUFFIX) ) + { + if ( !strcmp( key, tag->key ) ) + { + return tag->value; + } + } + return NULL; +} + +static void add_ffmpeg_attachment( hb_title_t *title, hb_stream_t *stream, int id ) +{ + AVStream *st = stream->ffmpeg_ic->streams[id]; + AVCodecContext *codec = st->codec; + + enum attachtype type; + switch ( codec->codec_id ) + { + case CODEC_ID_TTF: + type = FONT_TTF_ATTACH; + break; + default: + // Ignore unrecognized attachment type + return; + } + + hb_attachment_t *attachment = calloc( 1, sizeof(*attachment) ); + + // Copy the attachment name and data + attachment->type = type; + attachment->name = strdup( get_ffmpeg_metadata_value( st->metadata, "filename" ) ); + attachment->data = malloc( codec->extradata_size ); + memcpy( attachment->data, codec->extradata, codec->extradata_size ); + attachment->size = codec->extradata_size; + + hb_list_add(title->list_attachment, attachment); +} + static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) { AVFormatContext *ic = stream->ffmpeg_ic; @@ -3244,6 +3290,10 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) { add_ffmpeg_subtitle( title, stream, i ); } + else if ( ic->streams[i]->codec->codec_type == CODEC_TYPE_ATTACHMENT ) + { + add_ffmpeg_attachment( title, stream, i ); + } } title->container_name = strdup( ic->iformat->name ); diff --git a/libhb/sync.c b/libhb/sync.c index 53b3193a3..58628f316 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -247,6 +247,8 @@ void syncVideoClose( hb_work_object_t * w ) *********************************************************************** * **********************************************************************/ +static hb_buffer_t * copy_subtitle( hb_buffer_t * src ); + int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { @@ -562,12 +564,10 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, /* * Rewrite timestamps on subtitles that need it (on raw queue). */ - if( subtitle->source == CC608SUB || - subtitle->source == CC708SUB || - subtitle->source == SRTSUB || - subtitle->source == UTF8SUB || - subtitle->source == TX3GSUB || - subtitle->source == SSASUB) + // NOTE: It's probably fine to use this logic for passthru VOBSUBs as well, + // but I am currently preserving backwards compatibility with the old + // VOBSUB behavior, which uses the more complex logic following this if-statement. + if( subtitle->config.dest == PASSTHRUSUB && subtitle->source != VOBSUB ) { /* * Rewrite timestamps on subtitles that came from Closed Captions @@ -611,9 +611,13 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } } } + + continue; } - if( subtitle->source == VOBSUB ) + // For rendered subtitles (and, for backward compatibility, passthru VOBSUBs), + // delay pushing subtitle packets through the pipeline until the video catches up + if( subtitle->config.dest == RENDERSUB || subtitle->source == VOBSUB ) { hb_buffer_t * sub2; while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) ) @@ -681,7 +685,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, * Subtitle is on for less than three * seconds, extend the time that it is * displayed to make it easier to read. - * Make it 3 seconds or until the next + * Make it 2 seconds or until the next * subtitle is displayed. * * This is in response to Indochine which @@ -760,24 +764,23 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } /* If we have a subtitle for this picture, copy it */ - /* FIXME: we should avoid this memcpy */ if( sub ) { if( sub->size > 0 ) { if( subtitle->config.dest == RENDERSUB ) { + // Only allow one subtitle to be showing at once; ignore others if ( cur->sub == NULL ) { /* * Tack onto the video buffer for rendering */ - cur->sub = hb_buffer_init( sub->size ); - cur->sub->x = sub->x; - cur->sub->y = sub->y; - cur->sub->width = sub->width; - cur->sub->height = sub->height; - memcpy( cur->sub->data, sub->data, sub->size ); + /* FIXME: we should avoid this memcpy */ + cur->sub = copy_subtitle( sub ); + + // Leave the subtitle on the raw queue + // (until it no longer needs to be displayed) } } else { /* @@ -846,6 +849,29 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in, return HB_WORK_OK; } +static hb_buffer_t * copy_subtitle( hb_buffer_t * src_list ) +{ + hb_buffer_t * dst_list = NULL; + + hb_buffer_t * src; + hb_buffer_t * dst; + hb_buffer_t ** dst_ptr = &dst_list; + for ( src = src_list, dst_ptr = &dst_list; + src; + src = src->next_subpicture, dst_ptr = &dst->next_subpicture ) + { + (*dst_ptr) = hb_buffer_init( src->size ); + dst = (*dst_ptr); + dst->x = src->x; + dst->y = src->y; + dst->width = src->width; + dst->height = src->height; + memcpy( dst->data, src->data, src->size ); + } + + return dst_list; +} + // sync*Init does nothing because sync has a special initializer // that takes care of initializing video and all audio tracks int syncVideoInit( hb_work_object_t * w, hb_job_t * job) diff --git a/libhb/work.c b/libhb/work.c index 68bb6fe2f..3c3346d19 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -317,11 +317,7 @@ void hb_display_job_info( hb_job_t * job ) { hb_log( " * subtitle track %i, %s (id %x) %s [%s] -> %s%s%s", subtitle->track, subtitle->lang, subtitle->id, subtitle->format == PICTURESUB ? "Picture" : "Text", - subtitle->source == VOBSUB ? "VOBSUB" : - subtitle->source == CC608SUB || subtitle->source == CC708SUB ? "CC" : - subtitle->source == UTF8SUB ? "UTF-8" : - subtitle->source == TX3GSUB ? "TX3G" : - subtitle->source == SSASUB ? "SSA" : "Unknown", + hb_subsource_name( subtitle->source ), job->indepth_scan ? "Foreign Audio Search" : subtitle->config.dest == RENDERSUB ? "Render/Burn in" : "Pass-Through", subtitle->config.force ? ", Forced Only" : "", @@ -422,6 +418,7 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_audio_t * audio; hb_subtitle_t * subtitle; + hb_attachment_t * attachment; unsigned int subtitle_highest = 0; unsigned int subtitle_highest_id = 0; unsigned int subtitle_lowest = -1; @@ -819,6 +816,7 @@ static void do_job( hb_job_t * job, int cpu_count ) w = hb_get_work( WORK_DECSSASUB ); w->fifo_in = subtitle->fifo_in; w->fifo_out = subtitle->fifo_raw; + w->subtitle = subtitle; hb_list_add( job->list_work, w ); } diff --git a/macosx/Controller.m b/macosx/Controller.m index 7fbd5f280..9c7f1999a 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -3183,6 +3183,13 @@ bool one_burned = FALSE; continue; one_burned = TRUE; } + + /* Besides VOBSUBS we can also burn in SSA text subs */ + if (subt->source == SSASUB && burned) + { + sub_config.dest = RENDERSUB; + } + sub_config.force = force; sub_config.default_track = def; hb_subtitle_add( job, &sub_config, subtitle ); @@ -3672,13 +3679,20 @@ bool one_burned = FALSE; { sub_config.dest = PASSTHRUSUB; } - else if ( burned && subt->format == PICTURESUB ) + else if ( burned ) { // Only allow one subtitle to be burned into the video if (one_burned) continue; one_burned = TRUE; } + + /* Besides VOBSUBS we can also burn in SSA text subs */ + if (subt->source == SSASUB && burned) + { + sub_config.dest = RENDERSUB; + } + sub_config.force = force; sub_config.default_track = def; hb_subtitle_add( job, &sub_config, subtitle ); diff --git a/macosx/HBSubtitles.m b/macosx/HBSubtitles.m index aca6c023b..b084de525 100644 --- a/macosx/HBSubtitles.m +++ b/macosx/HBSubtitles.m @@ -284,6 +284,7 @@ { NSString * trackTypeString = @""; int isPictureSub = 0; + int canBeBurnedIn = 0; subtitle = (hb_subtitle_t *) hb_list_item( fTitle->list_subtitle, i ); sub_config = subtitle->config; @@ -291,12 +292,16 @@ { trackTypeString = @"- (Bitmap)"; isPictureSub = 1; + canBeBurnedIn = 1; } else { trackTypeString = @"- (Text)"; + if(subtitle->source == SSASUB) + { + canBeBurnedIn = 1; + } } - /* create a dictionary of source subtitle information to store in our array */ NSString *popupName = [NSString stringWithFormat:@"%d - %@ %@",i,[NSString stringWithUTF8String:subtitle->lang],trackTypeString]; NSMutableDictionary *newSubtitleSourceTrack = [[NSMutableDictionary alloc] init]; @@ -308,6 +313,8 @@ [newSubtitleSourceTrack setObject:@"Source" forKey:@"sourceTrackType"]; /* Subtitle Source track popup isPictureSub */ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:isPictureSub] forKey:@"sourceTrackisPictureSub"]; + /* Subtitle Source track popup canBeBurnedIn */ + [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:canBeBurnedIn] forKey:@"sourceTrackcanBeBurnedIn"]; [subtitleSourceArray addObject:newSubtitleSourceTrack]; [newSubtitleSourceTrack autorelease]; @@ -343,6 +350,8 @@ [newSubtitleTrack setObject:@"None" forKey:@"subtitleSourceTrackName"]; /* Subtitle Source track popup isPictureSub */ [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackisPictureSub"]; + /* Subtitle Source track popup canBeBurnedIn */ + [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackcanBeBurnedIn"]; /* Subtitle track forced state */ [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; /* Subtitle track burned state */ @@ -369,8 +378,10 @@ [newSubtitleSourceTrack setObject:@"SRT" forKey:@"subtitleSourceTrackType"]; /* Subtitle Source track type */ [newSubtitleSourceTrack setObject:filePath forKey:@"sourceSrtFilePath"]; - /* Subtitle Source track popup isPictureSub */ + /* Subtitle Source track popup isPictureSub */ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackisPictureSub"]; + /* Subtitle Source track popup canBeBurnedIn */ + [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackcanBeBurnedIn"]; [subtitleSourceArray addObject:newSubtitleSourceTrack]; [newSubtitleSourceTrack autorelease]; @@ -398,6 +409,8 @@ [newSubtitleSrtTrack setObject:displayname forKey:@"subtitleSourceTrackName"]; /* Subtitle Source track popup isPictureSub */ [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackisPictureSub"]; + /* Subtitle Source track popup canBeBurnedIn */ + [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackcanBeBurnedIn"]; /* Subtitle track forced state */ [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; /* Subtitle track burned state */ @@ -469,6 +482,8 @@ [newSubtitleSourceTrack setObject:filePath forKey:@"sourceSrtFilePath"]; /* Subtitle Source track popup isPictureSub */ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackisPictureSub"]; + /* Subtitle Source track popup canBeBurnedIn */ + [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackcanBeBurnedIn"]; [subtitleSourceArray addObject:newSubtitleSourceTrack]; [newSubtitleSourceTrack autorelease]; @@ -636,6 +651,7 @@ { int sourceSubtitleIndex; bool isPictureSub = FALSE; + bool canBeBurnedIn = FALSE; if (rowIndex == 0) { @@ -649,6 +665,7 @@ if (rowIndex == 0 && [anObject intValue] == 1)// we are Foreign Launguage Search, which is inherently bitmap { isPictureSub = TRUE; + canBeBurnedIn = TRUE; } else { @@ -656,6 +673,10 @@ { isPictureSub = TRUE; } + if ([[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackcanBeBurnedIn"] intValue] ==1) + { + canBeBurnedIn = TRUE; + } } if (isPictureSub == TRUE) { @@ -664,7 +685,15 @@ else { [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackisPictureSub"]; - /* if we are not picture sub, then we must be a text sub, handbrake does not support burning in text subs */ + } + if (canBeBurnedIn == TRUE) + { + [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleSourceTrackcanBeBurnedIn"]; + } + else + { + [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackcanBeBurnedIn"]; + /* the source track cannot be burned in, so uncheck the widget */ [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; } @@ -854,10 +883,10 @@ else if ([[aTableColumn identifier] isEqualToString:@"burned"]) { [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackBurned"] intValue]]; - /* Disable the "Burned-In" checkbox if a) the track is "None" or b) the subtitle track is text (we do not support burning in - * text subs) */ + /* Disable the "Burned-In" checkbox if a) the track is "None" or b) the subtitle track is text but not ssa (we do not support burning in + * non-ssa text subs) */ if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] == 0 || - [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackisPictureSub"] intValue] == 0) + [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackcanBeBurnedIn"] intValue] == 0) { [aCell setEnabled:NO]; } diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index c85135233..660787ae1 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -732,6 +732,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -741,6 +742,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -752,6 +755,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -765,6 +769,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -774,6 +779,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -785,6 +792,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -797,7 +805,7 @@ CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)"; CONFIGURATION_TEMP_DIR = "$(SYMROOT)"; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -833,6 +841,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -842,6 +851,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -853,6 +864,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -872,6 +884,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -881,6 +894,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -892,6 +907,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -925,7 +941,7 @@ CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)"; CONFIGURATION_TEMP_DIR = "$(SYMROOT)"; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -961,6 +977,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -970,6 +987,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -981,6 +1000,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1000,6 +1020,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1009,6 +1030,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1020,6 +1043,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1053,7 +1077,7 @@ CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)"; CONFIGURATION_TEMP_DIR = "$(SYMROOT)"; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1089,6 +1113,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1098,6 +1123,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1109,6 +1136,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1128,6 +1156,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1137,6 +1166,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1148,6 +1179,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1181,7 +1213,7 @@ CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)"; CONFIGURATION_TEMP_DIR = "$(SYMROOT)"; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1217,6 +1249,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1226,6 +1259,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1237,6 +1272,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1256,6 +1292,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1265,6 +1302,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1276,6 +1315,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1311,7 +1351,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1348,6 +1388,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1357,6 +1398,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1368,6 +1411,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1387,6 +1431,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1396,6 +1441,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1407,6 +1454,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1442,7 +1490,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1479,6 +1527,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1488,6 +1537,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1499,6 +1550,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1518,6 +1570,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1527,6 +1580,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1538,6 +1593,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1573,7 +1629,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1610,6 +1666,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1619,6 +1676,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1630,6 +1689,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1649,6 +1709,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1658,6 +1719,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1669,6 +1732,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1704,7 +1768,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1741,6 +1805,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1750,6 +1815,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1761,6 +1828,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1780,6 +1848,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1789,6 +1858,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1800,6 +1871,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrakeCLI; }; @@ -1880,6 +1952,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1889,6 +1962,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1900,6 +1975,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1923,6 +1999,7 @@ OTHER_LDFLAGS = ( "$(EXTERNAL_BUILD)/contrib/lib/libbluray.a", "$(EXTERNAL_BUILD)/contrib/lib/liba52.a", + "$(EXTERNAL_BUILD)/contrib/lib/libass.a", "$(EXTERNAL_BUILD)/contrib/lib/libavcodec.a", "$(EXTERNAL_BUILD)/contrib/lib/libavformat.a", "$(EXTERNAL_BUILD)/contrib/lib/libavutil.a", @@ -1932,6 +2009,8 @@ "$(EXTERNAL_BUILD)/contrib/lib/libdvdread.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaac.a", "$(EXTERNAL_BUILD)/contrib/lib/libfaad.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfontconfig.a", + "$(EXTERNAL_BUILD)/contrib/lib/libfreetype.a", "$(EXTERNAL_BUILD)/contrib/lib/libmkv.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp3lame.a", "$(EXTERNAL_BUILD)/contrib/lib/libmp4v2.a", @@ -1943,6 +2022,7 @@ "$(EXTERNAL_BUILD)/contrib/lib/libvorbis.a", "$(EXTERNAL_BUILD)/contrib/lib/libvorbisenc.a", "$(EXTERNAL_BUILD)/contrib/lib/libx264.a", + "$(EXTERNAL_BUILD)/contrib/lib/libxml2.a", ); PRODUCT_NAME = HandBrake; WARNING_CFLAGS = ( @@ -1962,7 +2042,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; @@ -1993,7 +2073,7 @@ CONFIGURATION_BUILD_DIR = "$(EXTERNAL_BUILD)"; CONFIGURATION_TEMP_DIR = "$(SYMROOT)"; EXTERNAL_BUILD = "$(EXTERNAL_SRC)/build.$(CONFIGURATION)"; - EXTERNAL_JOBS = 2; + EXTERNAL_JOBS = 1; EXTERNAL_METHOD = xcode; EXTERNAL_SRC = ..; FRAMEWORK_SEARCH_PATHS = "$(EXTERNAL_SRC)/macosx"; diff --git a/make/include/main.defs b/make/include/main.defs index a8ac0999d..4742f0f3e 100644 --- a/make/include/main.defs +++ b/make/include/main.defs @@ -19,7 +19,10 @@ endif MODULES += contrib/faac MODULES += contrib/faad2 MODULES += contrib/ffmpeg +MODULES += contrib/fontconfig +MODULES += contrib/freetype MODULES += contrib/lame +MODULES += contrib/libass MODULES += contrib/libdca MODULES += contrib/libdvdread MODULES += contrib/libdvdnav @@ -29,6 +32,7 @@ MODULES += contrib/libogg MODULES += contrib/libsamplerate MODULES += contrib/libtheora MODULES += contrib/libvorbis +MODULES += contrib/libxml2 MODULES += contrib/mp4v2 MODULES += contrib/mpeg2dec diff --git a/test/module.defs b/test/module.defs index 7dd323556..33d34d43e 100644 --- a/test/module.defs +++ b/test/module.defs @@ -10,8 +10,8 @@ TEST.c.o = $(patsubst $(SRC/)%.c,$(BUILD/)%.o,$(TEST.c)) TEST.exe = $(BUILD/)$(call TARGET.exe,$(HB.name)CLI) TEST.libs = $(LIBHB.a) $(foreach n, \ - a52 avcore avcodec avformat avutil dca dvdnav dvdread faac faad mkv mpeg2 mp3lame mp4v2 \ - ogg samplerate swscale theora vorbis vorbisenc x264 bluray, \ + a52 ass avcore avcodec avformat avutil dca dvdnav dvdread faac faad fontconfig freetype mkv mpeg2 mp3lame mp4v2 \ + ogg samplerate swscale theora vorbis vorbisenc x264 xml2 bluray, \ $(CONTRIB.build/)lib/lib$(n).a ) TEST.install.exe = $(DESTDIR)$(PREFIX/)bin/$(notdir $(TEST.exe)) diff --git a/test/test.c b/test/test.c index cff30ef4b..f5fb9ec57 100644 --- a/test/test.c +++ b/test/test.c @@ -440,10 +440,11 @@ static void PrintTitleInfo( hb_title_t * title ) for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - fprintf( stderr, " + %d, %s (iso639-2: %s) (%s)\n", + fprintf( stderr, " + %d, %s (iso639-2: %s) (%s)(%s)\n", i + 1, subtitle->lang, subtitle->iso639_2, - (subtitle->format == TEXTSUB) ? "Text" : "Bitmap"); + (subtitle->format == TEXTSUB) ? "Text" : "Bitmap", + hb_subsource_name(subtitle->source)); } if(title->detected_interlacing) @@ -1857,12 +1858,12 @@ static int HandleEvents( hb_handle_t * h ) } force = test_sub_list(subforce, token, pos); - - if ( !burn && subtitle->format == PICTURESUB) - { - sub_config.dest = PASSTHRUSUB; - } - else if ( burn && subtitle->format == PICTURESUB ) + + int supports_burn = + ( subtitle->source == VOBSUB ) || + ( subtitle->source == SSASUB ); + + if ( burn && supports_burn ) { // Only allow one subtitle to be burned into video if ( sub_burned ) @@ -1871,6 +1872,13 @@ static int HandleEvents( hb_handle_t * h ) continue; } sub_burned = 1; + + // Mark as burn-in + sub_config.dest = RENDERSUB; + } + else + { + sub_config.dest = PASSTHRUSUB; } sub_config.force = force; sub_config.default_track = def; |