summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2010-09-28 22:10:49 +0000
committerjstebbins <[email protected]>2010-09-28 22:10:49 +0000
commit03b2ce0e91c4e4ed44445a075ef5f35bc052b5b8 (patch)
tree24a1def4ca91cba98676508c6a3b1482ba131cb5
parentf1997be4ed1dd373316ac842685f18a6f8ab05ba (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
-rw-r--r--contrib/fontconfig/A00-mingw-disableShared.patch73
-rw-r--r--contrib/fontconfig/module.defs71
-rw-r--r--contrib/fontconfig/module.rules2
-rw-r--r--contrib/freetype/module.defs5
-rw-r--r--contrib/freetype/module.rules2
-rw-r--r--contrib/libass/A00-configure.patch84
-rw-r--r--contrib/libass/module.defs15
-rw-r--r--contrib/libass/module.rules2
-rw-r--r--contrib/libxml2/module.defs10
-rw-r--r--contrib/libxml2/module.rules2
-rw-r--r--contrib/mp4v2/module.defs7
-rw-r--r--gtk/src/Makefile.am4
-rw-r--r--gtk/src/hb-backend.c37
-rw-r--r--gtk/src/subtitlehandler.c54
-rw-r--r--libhb/common.c78
-rw-r--r--libhb/common.h35
-rw-r--r--libhb/decssasub.c381
-rw-r--r--libhb/decvobsub.c8
-rw-r--r--libhb/encavcodec.c23
-rw-r--r--libhb/hb.c13
-rw-r--r--libhb/internal.h5
-rw-r--r--libhb/module.defs8
-rw-r--r--libhb/render.c19
-rw-r--r--libhb/stream.c50
-rw-r--r--libhb/sync.c56
-rw-r--r--libhb/work.c8
-rw-r--r--macosx/Controller.m16
-rw-r--r--macosx/HBSubtitles.m41
-rw-r--r--macosx/HandBrake.xcodeproj/project.pbxproj100
-rw-r--r--make/include/main.defs4
-rw-r--r--test/module.defs4
-rw-r--r--test/test.c24
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;