]> granicus.if.org Git - handbrake/commitdiff
PGS (bluray) subtitle support \o/
authorjstebbins <jstebbins.hb@gmail.com>
Thu, 26 Apr 2012 19:11:03 +0000 (19:11 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Thu, 26 Apr 2012 19:11:03 +0000 (19:11 +0000)
Thanks to patches supplied by David Mitchell and Rob McMullen
we finally have PGS support.

I added a fix for libav pgs timestamp processing and
detection of forced subtitles to their work, then
made foreign audio search work with PGS subs.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4605 b64f7644-9d1e-0410-96f1-a4d463321fa5

38 files changed:
contrib/ffmpeg/A09-pgs-pts.patch [new file with mode: 0644]
gtk/src/callbacks.c
gtk/src/hb-backend.c
gtk/src/hb-backend.h
gtk/src/subtitlehandler.c
gtk/src/subtitlehandler.h
libhb/bd.c
libhb/common.c
libhb/common.h
libhb/cropscale.c
libhb/deblock.c
libhb/deccc608sub.c
libhb/decdca.c
libhb/decmpeg2.c
libhb/decomb.c
libhb/decpgssub.c [new file with mode: 0644]
libhb/decvobsub.c
libhb/deinterlace.c
libhb/denoise.c
libhb/detelecine.c
libhb/dvd.c
libhb/dvdnav.c
libhb/encavcodec.c
libhb/hb.c
libhb/hb_dict.c
libhb/internal.h
libhb/muxmkv.c
libhb/ports.c
libhb/rendersub.c
libhb/rotate.c
libhb/scan.c
libhb/stream.c
libhb/sync.c
libhb/vfr.c
libhb/work.c
macosx/Controller.m
macosx/HBSubtitles.m
test/test.c

diff --git a/contrib/ffmpeg/A09-pgs-pts.patch b/contrib/ffmpeg/A09-pgs-pts.patch
new file mode 100644 (file)
index 0000000..b03f5ac
--- /dev/null
@@ -0,0 +1,82 @@
+diff -Naur ffmpeg-v0.7-1696-gcae4f4b.orig/libavcodec/avcodec.h ffmpeg-v0.7-1696-gcae4f4b/libavcodec/avcodec.h
+--- ffmpeg-v0.7-1696-gcae4f4b.orig/libavcodec/avcodec.h        2011-11-03 12:29:48.000000000 +0100
++++ ffmpeg-v0.7-1696-gcae4f4b/libavcodec/avcodec.h     2012-04-22 10:59:41.122351884 +0200
+@@ -3193,6 +3193,7 @@
+     unsigned num_rects;
+     AVSubtitleRect **rects;
+     int64_t pts;    ///< Same as packet pts, in AV_TIME_BASE
++    uint8_t forced;
+ } AVSubtitle;
+ /* packet functions */
+diff -Naur ffmpeg-v0.7-1696-gcae4f4b.orig/libavcodec/pgssubdec.c ffmpeg-v0.7-1696-gcae4f4b/libavcodec/pgssubdec.c
+--- ffmpeg-v0.7-1696-gcae4f4b.orig/libavcodec/pgssubdec.c      2011-11-03 12:29:48.000000000 +0100
++++ ffmpeg-v0.7-1696-gcae4f4b/libavcodec/pgssubdec.c   2012-04-22 13:09:29.499671541 +0200
+@@ -45,6 +45,8 @@
+     int y;
+     int id_number;
+     int object_number;
++    uint8_t composition_flag;
++    int64_t pts;
+ } PGSSubPresentation;
+ typedef struct PGSSubPicture {
+@@ -271,7 +273,8 @@
+  * @todo TODO: Implement forcing of subtitles
+  */
+ static void parse_presentation_segment(AVCodecContext *avctx,
+-                                       const uint8_t *buf, int buf_size)
++                                       const uint8_t *buf, int buf_size,
++                                       int64_t pts)
+ {
+     PGSSubContext *ctx = avctx->priv_data;
+@@ -280,6 +283,8 @@
+     int w = bytestream_get_be16(&buf);
+     int h = bytestream_get_be16(&buf);
++    ctx->presentation.pts = pts;
++
+     av_dlog(avctx, "Video Dimensions %dx%d\n",
+             w, h);
+     if (av_image_check_size(w, h, 0, avctx) >= 0)
+@@ -299,16 +304,17 @@
+     buf += 3;
+     ctx->presentation.object_number = bytestream_get_byte(&buf);
++    ctx->presentation.composition_flag = 0;
+     if (!ctx->presentation.object_number)
+         return;
+     /*
+-     * Skip 4 bytes of unknown:
++     * Skip 3 bytes of unknown:
+      *     object_id_ref (2 bytes),
+      *     window_id_ref,
+-     *     composition_flag (0x80 - object cropped, 0x40 - object forced)
+      */
+-    buf += 4;
++    buf += 3;
++    ctx->presentation.composition_flag = bytestream_get_byte(&buf);
+     x = bytestream_get_be16(&buf);
+     y = bytestream_get_be16(&buf);
+@@ -356,6 +362,9 @@
+      */
+     memset(sub, 0, sizeof(*sub));
++    sub->pts = ctx->presentation.pts;
++    sub->forced = (ctx->presentation.composition_flag & 0x40) != 0;
++
+     // Blank if last object_number was 0.
+     // Note that this may be wrong for more complex subtitles.
+     if (!ctx->presentation.object_number)
+@@ -441,7 +450,7 @@
+             parse_picture_segment(avctx, buf, segment_length);
+             break;
+         case PRESENTATION_SEGMENT:
+-            parse_presentation_segment(avctx, buf, segment_length);
++            parse_presentation_segment(avctx, buf, segment_length, avpkt->pts);
+             break;
+         case WINDOW_SEGMENT:
+             /*
index 94a932d679608dbb7fe1bf23f3a9299cf925449c..ba0d569cc29304daf357b8161697204386180f66 100644 (file)
@@ -1268,6 +1268,7 @@ container_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
        ghb_clear_presets_selection(ud);
        ghb_live_reset(ud);
        ghb_subtitle_prune(ud);
+       ghb_subtitle_list_refresh_selected(ud);
        ghb_audio_list_refresh_selected(ud);
 }
 
index 2b2b663483010abb6e3f8fec7cb29f41f6c432eb..af1b890e5ad10e2a84b36ee891e70f2961489bb4 100644 (file)
@@ -1422,37 +1422,6 @@ ghb_subtitle_track_source(GValue *settings, gint track)
                return VOBSUB;
 }
 
-const char*
-ghb_subtitle_source_name(gint source)
-{
-       const gchar * name = "Unknown";
-       switch (source)
-       {
-               case VOBSUB:
-                       name = "VOBSUB";
-                       break;
-               case TX3GSUB:
-                       name = "TX3G";
-                       break;
-               case UTF8SUB:
-                       name = "UTF8";
-                       break;
-               case CC708SUB:
-               case CC608SUB:
-                       name = "CC";
-                       break;
-               case SRTSUB:
-                       name = "SRT";
-                       break;
-               case SSASUB:
-                       name = "SSA";
-                       break;
-               default:
-                       break;
-       }
-       return name;
-}
-
 const char*
 ghb_subtitle_track_source_name(GValue *settings, gint track)
 {
@@ -1491,7 +1460,7 @@ ghb_subtitle_track_source_name(GValue *settings, gint track)
        sub = hb_list_item( title->list_subtitle, track);
        if (sub != NULL)
        {
-               name = ghb_subtitle_source_name(sub->source);
+               name = hb_subsource_name(sub->source);
        }
 
 done:
@@ -2304,7 +2273,7 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
                        subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
                        options[ii] = g_strdup_printf("%d - %s (%s)", ii+1, 
                                subtitle->lang, 
-                               ghb_subtitle_source_name(subtitle->source));
+                               hb_subsource_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;
@@ -2681,18 +2650,6 @@ 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, 
@@ -2745,8 +2702,8 @@ ghb_find_subtitle_track(
                                continue;
 
                        subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
-                       if (((!force || (force && canForce(subtitle->source))) &&
-                                (!burn  || (burn  &&  canBurn(subtitle->source)))) &&
+                       if (((!force || (force && ghb_canForceSub(subtitle->source))) &&
+                                (!burn  || (burn  &&  ghb_canBurnSub(subtitle->source)))) &&
                                ((strcmp(lang, subtitle->iso639_2) == 0) ||
                                 (strcmp(lang, "und") == 0)))
                        {
@@ -5106,7 +5063,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
                                {
                                        sub_config.dest = PASSTHRUSUB;
                                }
-                               else if ( burned && canBurn(subt->source) )
+                               else if ( burned && ghb_canBurnSub(subt->source) )
                                {
                                        // Only allow one subtitle to be burned into the video
                                        if (one_burned)
index 407dc73155d1274689ca51c14d922fc23f38d0e8..22f3f6770aa643e63a142140425c4a31fff05faf 100644 (file)
@@ -163,7 +163,6 @@ gint ghb_get_title_number(gint titleindex);
 int ghb_get_title_count();
 gint ghb_subtitle_track_source(GValue *settings, gint track);
 const char* ghb_subtitle_track_source_name(GValue *settings, gint track);
-const char* ghb_subtitle_source_name(gint source);
 gchar* ghb_subtitle_track_lang(GValue *settings, gint track);
 
 gboolean ghb_validate_vquality(GValue *settings);
index ffe38a0e6f9869fd718200004aa518a20ef4ddb6..5b5036520818b26e95e3c7441ccc215b04281a9a 100644 (file)
@@ -42,16 +42,22 @@ free_subtitle_key(gpointer data)
                g_free(data);
 }
 
-static gboolean
-canBurn(int source)
+gboolean
+ghb_canPassSub(int source, int mux)
 {
-       return (source == VOBSUB || source == SSASUB);
+       return hb_subtitle_can_pass(source, mux);
 }
 
-static gboolean
-canForce(int source)
+gboolean
+ghb_canBurnSub(int source)
 {
-       return (source == VOBSUB);
+       return hb_subtitle_can_burn(source);
+}
+
+gboolean
+ghb_canForceSub(int source)
+{
+    return hb_subtitle_can_force(source);
 }
 
 gboolean
@@ -86,7 +92,6 @@ ghb_subtitle_exclusive_burn_settings(GValue *settings, gint index)
        {
                if (ii != index)
                {
-printf("settings burn %d also %d\n", index, ii);
                        subsettings = ghb_array_get_nth(subtitle_list, ii);
                        ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE);
                }
@@ -114,7 +119,6 @@ ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index)
                gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
                if (ii != index)
                {
-printf("ui burn %d also %d\n", index, ii);
                        subsettings = ghb_array_get_nth(subtitle_list, ii);
                        ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE);
                        gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1);
@@ -226,7 +230,8 @@ ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings)
        // Add the current subtitle settings to the list.
        GValue *subtitle_list;
        gint count;
-       gboolean burned;
+       gboolean burned, forced;
+       gint source, mux;
        const gchar *track;
        const gchar *lang;
        
@@ -256,9 +261,29 @@ ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings)
        lang = ghb_settings_combo_string(subsettings, "SubtitleTrack");
        ghb_settings_set_string(subsettings, "SubtitleLanguage", lang);
 
+       mux = ghb_settings_combo_int(settings, "FileFormat");
+       source = ghb_settings_get_int(subsettings, "SubtitleSource");
+       burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned");
+       if (burned && !ghb_canBurnSub(source))
+       {
+               burned = FALSE;
+               ghb_settings_set_boolean(subsettings, "SubtitleBurned", burned);
+       }
+       if (!burned && !ghb_canPassSub(source, mux))
+       {
+               burned = TRUE;
+               ghb_settings_set_boolean(subsettings, "SubtitleBurned", burned);
+               ghb_settings_set_boolean(subsettings, "SubtitleDefaultTrack", FALSE);
+       }
+       forced = ghb_settings_get_boolean(subsettings, "SubtitleForced");
+       if (forced && !ghb_canForceSub(source))
+       {
+               forced = FALSE;
+               ghb_settings_set_boolean(subsettings, "SubtitleForced", forced);
+       }
+
        ghb_array_append(subtitle_list, subsettings);
 
-       burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned");
        if (burned)
                ghb_subtitle_exclusive_burn_settings(settings, count);
        return TRUE;
@@ -300,6 +325,7 @@ add_all_pref_subtitles(signal_user_data_t *ud)
        for (ii = 0; ii < count; ii++)
        {
                subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii));
+               gboolean force = ghb_settings_get_boolean(subtitle, "SubtitleForced");
                lang = ghb_settings_get_string(subtitle, "SubtitleLanguage");
                // If there are multiple subtitles using the same language, then
                // select sequential tracks for each.  The hash keeps track 
@@ -417,7 +443,7 @@ ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings)
                GValue *subsettings;
                gboolean burn;
 
-               track = ghb_find_subtitle_track(titleindex, pref_lang, FALSE, FALSE, VOBSUB, track_indices);
+               track = ghb_find_subtitle_track(titleindex, pref_lang, FALSE, FALSE, PGSSUB, track_indices);
                if (track >= -1)
                {
                        int source;
@@ -463,7 +489,6 @@ ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings)
                if (track >= 0)
                {
                        int source;
-
                        subsettings = ghb_dict_value_new();
                        ghb_settings_set_int(subsettings, "SubtitleTrack", track);
                        source = ghb_subtitle_track_source(settings, track);
@@ -606,8 +631,10 @@ subtitle_forced_toggled_cb(
        settings = ghb_array_get_nth(subtitle_list, row);
 
        source = ghb_settings_get_int(settings, "SubtitleSource");
-       if (!canForce(source))
+       if (!ghb_canForceSub(source))
+    {
                return;
+    }
 
        ghb_settings_set_boolean(settings, "SubtitleForced", active);
        gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1);
@@ -630,7 +657,7 @@ subtitle_burned_toggled_cb(
        GValue *subtitle_list;
        gint count;
        GValue *settings;
-       gint source;
+       gint source, mux;
 
        g_debug("burned toggled");
        tp = gtk_tree_path_new_from_string (path);
@@ -654,7 +681,10 @@ subtitle_burned_toggled_cb(
 
        settings = ghb_array_get_nth(subtitle_list, row);
        source = ghb_settings_get_int(settings, "SubtitleSource");
-       if (!canBurn(source))
+       if (!ghb_canBurnSub(source))
+               return;
+       mux = ghb_settings_combo_int(ud->settings, "FileFormat");
+       if (!active && !hb_subtitle_can_pass(source, mux))
                return;
 
        ghb_settings_set_boolean(settings, "SubtitleBurned", active);
@@ -711,6 +741,12 @@ subtitle_default_toggled_cb(
 
        settings = ghb_array_get_nth(subtitle_list, row);
 
+       int source, mux;
+       source = ghb_settings_get_int(settings, "SubtitleSource");
+       mux = ghb_settings_combo_int(ud->settings, "FileFormat");
+       if (active && !hb_subtitle_can_pass(source, mux))
+               return;
+
        ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active);
        gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1);
 
@@ -724,8 +760,8 @@ subtitle_default_toggled_cb(
        ghb_live_reset(ud);
 }
 
-static void
-subtitle_list_refresh_selected(signal_user_data_t *ud)
+void
+ghb_subtitle_list_refresh_selected(signal_user_data_t *ud)
 {
        GtkTreeView *treeview;
        GtkTreePath *treepath;
@@ -760,22 +796,34 @@ subtitle_list_refresh_selected(signal_user_data_t *ud)
                        return;
                settings = ghb_array_get_nth(subtitle_list, row);
 
-               def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
+               burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
 
                gint i_source;
                i_source = ghb_settings_get_int(settings, "SubtitleSource");
-               if (!canBurn(i_source))
+               if (!ghb_canBurnSub(i_source))
                {
                        burned = FALSE;
                        ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
                }
-               if (!canForce(i_source))
+
+               gint i_mux;
+               i_mux = ghb_settings_combo_int(ud->settings, "FileFormat");
+               if (!burned && !ghb_canPassSub(i_source, i_mux))
+               {
+                       burned = TRUE;
+                       ghb_settings_set_boolean(settings, "SubtitleBurned", burned);
+                       ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE);
+               }
+
+               forced = ghb_settings_get_boolean(settings, "SubtitleForced");
+               if (!ghb_canForceSub(i_source))
                {
-                       // Force only apply to VOBSUBS
                        forced = FALSE;
                        ghb_settings_set_boolean(settings, "SubtitleForced", forced);
                }
 
+               def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
+
                if (i_source == SRTSUB)
                {
                        const gchar *lang;
@@ -801,24 +849,18 @@ subtitle_list_refresh_selected(signal_user_data_t *ud)
                        }
                        g_free(code);
                        offset = ghb_settings_get_int(settings, "SrtOffset");
-
-                       forced = FALSE;
-                       burned = FALSE;
                }
                else
                {
                        track = g_strdup(
                                ghb_settings_combo_option(settings, "SubtitleTrack"));
-                       source = g_strdup(ghb_subtitle_source_name(i_source));
+                       source = g_strdup(hb_subsource_name(i_source));
                        s_track = ghb_settings_get_string(settings, "SubtitleTrack");
-
-                       forced = ghb_settings_get_boolean(settings, "SubtitleForced");
-                       burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
                }
 
-               if (canBurn(i_source))
+               if (ghb_canBurnSub(i_source))
                        allow_burn = TRUE;
-               if (canForce(i_source))
+               if (ghb_canForceSub(i_source))
                        allow_force = TRUE;
 
                gtk_list_store_set(GTK_LIST_STORE(store), &iter, 
@@ -864,7 +906,7 @@ subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
                ghb_settings_set_int(settings, "SubtitleSource", source);
                lang = ghb_settings_combo_string(settings, "SubtitleTrack");
                ghb_settings_set_string(settings, "SubtitleLanguage", lang);
-               subtitle_list_refresh_selected(ud);
+               ghb_subtitle_list_refresh_selected(ud);
                ghb_live_reset(ud);
        }
        ghb_live_reset(ud);
@@ -882,7 +924,7 @@ srt_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
        if (settings != NULL)
        {
                ghb_widget_to_setting(settings, widget);
-               subtitle_list_refresh_selected(ud);
+               ghb_subtitle_list_refresh_selected(ud);
 
                ghb_live_reset(ud);
        }
@@ -902,7 +944,7 @@ srt_file_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
                gchar *filename, *dirname;
 
                ghb_widget_to_setting(settings, widget);
-               subtitle_list_refresh_selected(ud);
+               ghb_subtitle_list_refresh_selected(ud);
 
                ghb_live_reset(ud);
 
@@ -936,7 +978,7 @@ srt_lang_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
                const gchar *lang;
 
                ghb_widget_to_setting(settings, widget);
-               subtitle_list_refresh_selected(ud);
+               ghb_subtitle_list_refresh_selected(ud);
 
                ghb_live_reset(ud);
 
@@ -982,7 +1024,7 @@ add_to_subtitle_list(
        GtkTreeIter iter;
        GtkListStore *store;
        GtkTreeSelection *selection;
-       const gchar *track, *source;
+       const gchar *track;
        gboolean forced, burned, def;
        gchar *s_track;
        gint i_source;
@@ -1001,11 +1043,10 @@ add_to_subtitle_list(
 
        s_track = ghb_settings_get_string(settings, "SubtitleTrack");
        i_source = ghb_settings_get_int(settings, "SubtitleSource");
-       source = ghb_subtitle_source_name(i_source);
 
-       if (canBurn(i_source))
+       if (ghb_canBurnSub(i_source))
                allow_burn = TRUE;
-       if (canForce(i_source))
+       if (ghb_canForceSub(i_source))
                allow_force = TRUE;
 
        gtk_list_store_append(store, &iter);
@@ -1251,7 +1292,7 @@ subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
        // Add the current subtitle settings to the list.
        GValue *settings;
        gboolean burned = FALSE;
-       gint track, source;
+       gint track, source, mux;
        
        g_debug("subtitle_add_clicked_cb ()");
 
@@ -1260,6 +1301,11 @@ subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
        settings = ghb_dict_value_new();
        ghb_settings_set_int(settings, "SubtitleTrack", track);
        source = ghb_subtitle_track_source(ud->settings, track);
+
+       // Initialize to passthru if possible, else burn
+       mux = ghb_settings_combo_int(ud->settings, "FileFormat");
+       burned = !hb_subtitle_can_pass(source, mux);
+
        ghb_settings_set_int(settings, "SubtitleSource", source);
        ghb_settings_take_value(settings, "SubtitleForced", 
                                                        ghb_boolean_value_new(FALSE));
@@ -1331,7 +1377,6 @@ void
 ghb_subtitle_prune(signal_user_data_t *ud)
 {
        GtkTreeView  *tv;
-       GtkTreeModel *tm;
        GValue *subtitle_list;
        gint count, ii;
        gint first_track = 0, one_burned = 0;
@@ -1343,7 +1388,6 @@ ghb_subtitle_prune(signal_user_data_t *ud)
 
        tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list"));
        g_return_if_fail(tv != NULL);
-       tm = gtk_tree_view_get_model(tv);
        for (ii = count-1; ii >= 0; ii--)
        {
                gboolean burned;
index ac662499f2ff2d50c62b03cf0e259b14ae0b59f5..267b79bc2ef68b9b55b87a0f5cd030db0d7e00b3 100644 (file)
@@ -35,5 +35,9 @@ gint ghb_selected_subtitle_row(signal_user_data_t *ud);
 void ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings);
 void ghb_subtitle_prune(signal_user_data_t *ud);
 gboolean ghb_soft_in_subtitle_list(GValue *subtitle_list);
+gboolean ghb_canBurnSub(int source);
+gboolean ghb_canForceSub(int source);
+gboolean ghb_canPassSub(int source, int mux);
+void ghb_subtitle_list_refresh_selected(signal_user_data_t *ud);
 
 #endif // _SUBTITLEHANDLER_H_
index 9ec4c078a6b0be239b3fe7c5ff52648fdc10bb12..bb051115a2e7c46182a588a30b71397b25ffec80 100644 (file)
@@ -81,6 +81,44 @@ int hb_bd_title_count( hb_bd_t * d )
     return d->title_count;
 }
 
+static void add_subtitle(int track, hb_list_t *list_subtitle, BLURAY_STREAM_INFO *bdsub, uint32_t codec)
+{
+    hb_subtitle_t * subtitle;
+    iso639_lang_t * lang;
+
+    subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
+
+    subtitle->track = track;
+    subtitle->id = bdsub->pid;
+    lang = lang_for_code2( (char*)bdsub->lang );
+    snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
+              strlen(lang->native_name) ? lang->native_name : lang->eng_name);
+    snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
+              lang->iso639_2);
+
+    switch ( bdsub->coding_type )
+    {
+        case BLURAY_STREAM_TYPE_SUB_PG:
+            subtitle->source = PGSSUB;
+            subtitle->format = PICTURESUB;
+            subtitle->config.dest = RENDERSUB;
+            break;
+        default:
+            // Unrecognized, don't add to list
+            free( subtitle );
+            return;
+    }
+    subtitle->reg_desc = STR4_TO_UINT32("HDMV");
+    subtitle->stream_type = bdsub->coding_type;
+    subtitle->codec = codec;
+
+    hb_log( "bd: subtitle id=0x%x, lang=%s, 3cc=%s", subtitle->id,
+            subtitle->lang, subtitle->iso639_2 );
+
+    hb_list_add( list_subtitle, subtitle );
+    return;
+}
+
 static void add_audio(int track, hb_list_t *list_audio, BLURAY_STREAM_INFO *bdaudio, int substream_type, uint32_t codec, uint32_t codec_param)
 {
     hb_audio_t * audio;
@@ -89,6 +127,7 @@ static void add_audio(int track, hb_list_t *list_audio, BLURAY_STREAM_INFO *bdau
     audio = calloc( sizeof( hb_audio_t ), 1 );
 
     audio->id = (substream_type << 16) | bdaudio->pid;
+    audio->config.in.reg_desc = STR4_TO_UINT32("HDMV");
     audio->config.in.stream_type = bdaudio->coding_type;
     audio->config.in.substream_type = substream_type;
     audio->config.in.codec = codec;
@@ -393,6 +432,25 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
         }
     }
 
+    // Add all the subtitles found in the above clip.
+    for ( ii = 0; ii < ti->clips[audio_clip_index].pg_stream_count; ii++ )
+    {
+        BLURAY_STREAM_INFO * bdpgs;
+
+        bdpgs = &ti->clips[audio_clip_index].pg_streams[ii];
+
+        switch( bdpgs->coding_type )
+        {
+            case BLURAY_STREAM_TYPE_SUB_PG:
+                add_subtitle(ii, title->list_subtitle, bdpgs, WORK_DECPGSSUB);
+                break;
+            default:
+                hb_log( "scan: unknown subtitle pid 0x%x codec 0x%x",
+                        bdpgs->pid, bdpgs->coding_type );
+                break;
+        }
+    }
+
     /* Chapters */
     for ( ii = 0; ii < ti->chapter_count; ii++ )
     {
index 3f30974854c2debf2c218debd08c7abe0097894c..23c6ea21ee7f6c1f466139085d1c0b31b973a60c 100644 (file)
@@ -1751,6 +1751,7 @@ int hb_subtitle_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlec
         return 0;
     }
     subtitle->config = *subtitlecfg;
+    subtitle->out_track = hb_list_count(job->list_subtitle) + 1;
     hb_list_add(job->list_subtitle, subtitle);
     return 1;
 }
@@ -1768,6 +1769,7 @@ int hb_srt_add( const hb_job_t * job,
     subtitle->id = (hb_list_count(job->list_subtitle) << 8) | 0xFF;
     subtitle->format = TEXTSUB;
     subtitle->source = SRTSUB;
+    subtitle->codec = WORK_DECSRTSUB;
 
     language = lang_for_code2( lang );
 
@@ -1786,6 +1788,61 @@ int hb_srt_add( const hb_job_t * job,
     return retval;
 }
 
+int hb_subtitle_can_force( int source )
+{
+    return source == VOBSUB || source == PGSSUB;
+}
+
+int hb_subtitle_can_burn( int source )
+{
+    return source == VOBSUB || source == PGSSUB || source == SSASUB;
+}
+
+int hb_subtitle_can_pass( int source, int mux )
+{
+    if ( mux == HB_MUX_MKV )
+    {
+        switch( source )
+        {
+            case PGSSUB:
+            case VOBSUB:
+            case SSASUB:
+            case SRTSUB:
+            case UTF8SUB:
+            case TX3GSUB:
+            case CC608SUB:
+            case CC708SUB:
+                return 1;
+
+            default:
+                return 0;
+        }
+    }
+    else if ( mux == HB_MUX_MP4 )
+    {
+        switch( source )
+        {
+            case VOBSUB:
+            case SSASUB:
+            case SRTSUB:
+            case UTF8SUB:
+            case TX3GSUB:
+            case CC608SUB:
+            case CC708SUB:
+                return 1;
+
+            default:
+                return 0;
+        }
+    }
+    else
+    {
+        // Internal error. Should never get here.
+        hb_error("internel error.  Bad mux %d\n", mux);
+        return 0;
+    }
+}
+
 char * hb_strdup_printf( const char * fmt, ... )
 {
     int       len;
@@ -1964,6 +2021,8 @@ const char * hb_subsource_name( int source )
             return "TX3G";
         case SSASUB:
             return "SSA";
+        case PGSSUB:
+            return "PGS";
         default:
             return "Unknown";
     }
index d38f77a0bc7b7e28a117bb15090df1599f782e4d..741c32e037f583462dd450ec3d5286892d93b845 100644 (file)
@@ -122,6 +122,9 @@ 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);
+int hb_subtitle_can_force( int source );
+int hb_subtitle_can_burn( int source );
+int hb_subtitle_can_pass( int source, int mux );
 
 hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src);
 
@@ -610,11 +613,12 @@ struct hb_subtitle_s
 {
     int  id;
     int  track;
+    int  out_track;
 
     hb_subtitle_config_t config;
 
     enum subtype { PICTURESUB, TEXTSUB } format;
-    enum subsource { VOBSUB, SRTSUB, CC608SUB, /*unused*/CC708SUB, UTF8SUB, TX3GSUB, SSASUB } source;
+    enum subsource { VOBSUB, SRTSUB, CC608SUB, /*unused*/CC708SUB, UTF8SUB, TX3GSUB, SSASUB, PGSSUB } source;
     char lang[1024];
     char iso639_2[4];
     uint8_t type; /* Closed Caption, Childrens, Directors etc */
@@ -622,6 +626,7 @@ struct hb_subtitle_s
     // Color lookup table for VOB subtitle tracks. Each entry is in YCbCr format.
     // Must be filled out by the demuxer for VOB subtitle tracks.
     uint32_t    palette[16];
+    uint8_t     palette_set;
     int         width;
     int         height;
     
@@ -634,6 +639,11 @@ struct hb_subtitle_s
 
 #ifdef __LIBHB__
     /* Internal data */
+    PRIVATE uint32_t codec;         /* Input "codec" */
+    PRIVATE uint32_t reg_desc;      /* registration descriptor of source */
+    PRIVATE uint32_t stream_type;   /* stream type from source stream */
+    PRIVATE uint32_t substream_type;/* substream for multiplexed streams */
+
     hb_fifo_t * fifo_in;  /* SPU ES */
     hb_fifo_t * fifo_raw; /* Decoded SPU */
     hb_fifo_t * fifo_sync;/* Synced */
@@ -873,6 +883,7 @@ extern hb_work_object_t hb_decsrtsub;
 extern hb_work_object_t hb_decutf8sub;
 extern hb_work_object_t hb_dectx3gsub;
 extern hb_work_object_t hb_decssasub;
+extern hb_work_object_t hb_decpgssub;
 extern hb_work_object_t hb_encavcodec;
 extern hb_work_object_t hb_encx264;
 extern hb_work_object_t hb_enctheora;
@@ -920,6 +931,7 @@ struct hb_filter_object_s
 {
     int                     id;
     int                     enforce_order;
+    int                     init_index;
     char                  * name;
     char                  * settings;
 
index 11a22a44e400d96fbd9f8fc9edadad9d80f9c970..c11e931ee2e92189069c0401b91f1de1f92baecc 100644 (file)
@@ -30,6 +30,7 @@ hb_filter_object_t hb_filter_crop_scale =
 {
     .id            = HB_FILTER_CROP_SCALE,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Crop and Scale",
     .settings      = NULL,
     .init          = hb_crop_scale_init,
index dab622abc8d948467128f26a1f35973af24a2b47..6d1f1aaecfc1ba0818765cb9051febcf9bb4dcaf 100644 (file)
@@ -63,6 +63,7 @@ hb_filter_object_t hb_filter_deblock =
 {
     .id            = HB_FILTER_DEBLOCK,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Deblock (pp7)",
     .settings      = NULL,
     .init          = hb_deblock_init,
index aaa3d020d5813d9357ae90b5a298dd6258c246ba..1d16410e45a8fa6f8071596fb68a14fdcb94e7ca 100644 (file)
@@ -1607,7 +1607,7 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb)
     if (debug_608)
     {
         hb_log ("\n- - - SRT caption - - -\n");
-        hb_log (timeline);
+        hb_log ("%s", timeline);
     }
     //fwrite (enc_buffer,enc_buffer_used,1,wb->fh);            
     XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used);
index 1e6e4192cf8c35a6506359156be57e3faec3b1a3..5bc11800755c95cbd34a577047c40e847dffbdee 100644 (file)
@@ -157,7 +157,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
     hb_buffer_t * buf;
     hb_audio_t  * audio = w->audio;
     int           i, j, k;
-    int64_t       pts, pos;
+    int64_t       pts;
     uint64_t      upts, upos;
     int           num_blocks;
 
@@ -203,7 +203,6 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
     /* Get the whole frame */
     hb_list_getbytes( pv->list, pv->frame, pv->size, &upts, &upos );
     pts = (int64_t)upts;
-    pos = (int64_t)upos;
 
     if ( pts != pv->last_buf_pts )
     {
index 82ba78e31bdda5b7ca25ddd77cd3998416635037..95b189af05679d8caab7ec08c86335f497c37d02 100644 (file)
@@ -654,6 +654,7 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
                 subtitle->format = TEXTSUB;
                 subtitle->source = CC608SUB;
                 subtitle->config.dest = PASSTHRUSUB;
+                subtitle->codec = WORK_DECCC608;
                 subtitle->type = 5; 
                 snprintf( subtitle->lang, sizeof( subtitle->lang ), "Closed Captions");
                 /*
@@ -664,7 +665,7 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
                 if( audio )
                 {
                     snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), 
-                              audio->config.lang.iso639_2);
+                              "%s", audio->config.lang.iso639_2);
                 } else {
                     snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "und");
                 }
index 7d911ff28968cac1c655a03692bd3315c32e48e6..fae95caea2d03e523436149950c56579c716f20a 100644 (file)
@@ -233,6 +233,7 @@ hb_filter_object_t hb_filter_decomb =
 {
     .id            = HB_FILTER_DECOMB,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Decomb",
     .settings      = NULL,
     .init          = hb_decomb_init,
diff --git a/libhb/decpgssub.c b/libhb/decpgssub.c
new file mode 100644 (file)
index 0000000..1b0f7e4
--- /dev/null
@@ -0,0 +1,268 @@
+#include "hb.h"
+#include "hbffmpeg.h"
+
+struct hb_work_private_s
+{
+    AVCodecContext * context;
+    hb_job_t * job;
+    // For PGS subs, when doing passthru, we don't know if we need a
+    // packet until we have processed several packets.  So we cache
+    // all the packets we see until libav returns a subtitle with
+    // the information we need.
+    hb_buffer_t * list_pass_buffer;
+    hb_buffer_t * last_pass_buffer;
+    // It is possible for multiple subtitles to be enncapsulated in
+    // one packet.  This won't happen for PGS subs, but may for other
+    // types of subtitles.  Since I plan to generalize this code to handle
+    // other than PGS, we will need to keep a list of all subtitles seen
+    // while parsing an input packet.
+    hb_buffer_t * list_buffer;
+    hb_buffer_t * last_buffer;
+};
+
+static int decsubInit( hb_work_object_t * w, hb_job_t * job )
+{
+    AVCodec *codec = avcodec_find_decoder( CODEC_ID_HDMV_PGS_SUBTITLE );
+    AVCodecContext *context = avcodec_alloc_context3( codec );
+    context->codec = codec;
+
+    hb_work_private_t * pv;
+    pv = calloc( 1, sizeof( hb_work_private_t ) );
+    w->private_data = pv;
+
+    pv->context = context;
+    pv->job = job;
+
+    return 0;
+}
+
+static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
+                hb_buffer_t ** buf_out )
+{
+    hb_work_private_t * pv = w->private_data;
+    hb_buffer_t * in = *buf_in;
+
+    if ( in->size <= 0 )
+    {
+        /* EOF on input stream - send it downstream & say that we're done */
+        if ( pv->list_buffer == NULL )
+        {
+            pv->list_buffer = pv->last_buffer = in;
+        }
+        else
+        {
+            pv->last_buffer->next = in;
+        }
+        *buf_in = NULL;
+        *buf_out = pv->list_buffer;
+        pv->list_buffer = NULL;
+
+        return HB_WORK_DONE;
+    }
+
+    if ( !pv->job->indepth_scan &&
+         w->subtitle->config.dest == PASSTHRUSUB &&
+         hb_subtitle_can_pass( PGSSUB, pv->job->mux ) )
+    {
+        // Append to buffer list.  It will be sent to fifo after we determine
+        // if this is a packet we need.
+        if ( pv->list_pass_buffer == NULL )
+        {
+            pv->list_pass_buffer = pv->last_pass_buffer = in;
+        }
+        else
+        {
+            pv->last_pass_buffer->next = in;
+            pv->last_pass_buffer = in;
+        }
+        // We are keeping the buffer, so prevent the filter loop from
+        // deleting it.
+        *buf_in = NULL;
+    }
+
+    AVSubtitle subtitle;
+    memset( &subtitle, 0, sizeof(subtitle) );
+
+    AVPacket avp;
+    av_init_packet( &avp );
+    avp.data = in->data;
+    avp.size = in->size;
+    // libav wants pkt pts in AV_TIME_BASE units
+    avp.pts = av_rescale(in->s.start, AV_TIME_BASE, 90000);
+
+    int has_subtitle = 0;
+
+    do
+    {
+        int usedBytes = avcodec_decode_subtitle2( pv->context, &subtitle, &has_subtitle, &avp );
+        if (usedBytes < 0)
+        {
+            hb_log("unable to decode subtitle with %d bytes.", avp.size);
+            return HB_WORK_OK;
+        }
+
+        if (usedBytes <= avp.size)
+        {
+            avp.data += usedBytes;
+            avp.size -= usedBytes;
+        }
+        else
+        {
+            avp.size = 0;
+        }
+
+        // The sub is "usable" if:
+        // 1. libav returned a sub AND
+        // 2. we are scanning for foreign audio subs OR
+        // 3. we want all subs (e.g. not forced) OR
+        // 4. the sub is forced and we only want forced OR
+        // 5. subtitle clears the previous sub (these are never forced)
+        //    subtitle.num_rects == 0
+        uint8_t useable_sub =
+                    pv->job->indepth_scan ||
+                    subtitle.num_rects == 0 ||
+                    !w->subtitle->config.force ||
+                    ( w->subtitle->config.force && subtitle.forced );
+
+        if (has_subtitle && useable_sub)
+        {
+            int64_t pts = av_rescale(subtitle.pts, 90000, AV_TIME_BASE);
+            hb_buffer_t * out = NULL;
+
+            if( pv->job->indepth_scan )
+            {
+                if (subtitle.forced)
+                {
+                    w->subtitle->forced_hits++;
+                }
+            }
+            else if ( w->subtitle->config.dest == PASSTHRUSUB &&
+                 hb_subtitle_can_pass( PGSSUB, pv->job->mux ) )
+            {
+                out = pv->list_pass_buffer;
+                pv->list_pass_buffer = NULL;
+            }
+            else
+            {
+                if (subtitle.num_rects != 0)
+                {
+                    unsigned ii;
+                    for (ii = 0; ii < subtitle.num_rects; ii++)
+                    {
+                        AVSubtitleRect *rect = subtitle.rects[ii];
+
+                        out = hb_frame_buffer_init(
+                                PIX_FMT_YUVA420P, rect->w, rect->h );
+
+                        out->s.id     = in->s.id;
+                        out->sequence = in->sequence;
+                        out->s.start  = pts;
+                        out->s.stop   = 0;
+                        out->f.x      = rect->x;
+                        out->f.y      = rect->y;
+
+                        uint8_t *lum     = out->plane[0].data;
+                        uint8_t *chromaU = out->plane[1].data;
+                        uint8_t *chromaV = out->plane[2].data;
+                        uint8_t *alpha   = out->plane[3].data;
+
+                        int xx, yy;
+                        for (yy = 0; yy < rect->h; yy++)
+                        {
+                            for (xx = 0; xx < rect->w; xx++)
+                            {
+                                uint32_t argb, yuv;
+                                int pixel;
+                                uint8_t color;
+
+                                pixel = yy * rect->w + xx;
+                                color = rect->pict.data[0][pixel];
+                                argb = ((uint32_t*)rect->pict.data[1])[color];
+                                yuv = hb_rgb2yuv(argb);
+
+                                lum[xx] = (yuv >> 16) & 0xff;
+                                alpha[xx] = (argb >> 24) & 0xff;
+                                if ((xx & 1) == 0 && (yy & 1) == 0)
+                                {
+                                    chromaV[xx>>1] = (yuv >> 8) & 0xff;
+                                    chromaU[xx>>1] = yuv & 0xff;
+                                }
+                            }
+                            lum += out->plane[0].stride;
+                            if ((yy & 1) == 0)
+                            {
+                                chromaU += out->plane[1].stride;
+                                chromaV += out->plane[2].stride;
+                            }
+                            alpha += out->plane[3].stride;
+                        }
+
+                        if ( pv->list_buffer == NULL )
+                        {
+                            pv->list_buffer = pv->last_buffer = out;
+                        }
+                        else
+                        {
+                            pv->last_buffer->next = out;
+                            pv->last_buffer = out;
+                        }
+                        out = NULL;
+                    }
+                }
+                else
+                {
+                    out = hb_buffer_init( 1 );
+
+                    out->s.id     = in->s.id;
+                    out->s.start  = pts;
+                    out->s.stop   = 0;
+                    out->f.x      = 0;
+                    out->f.y      = 0;
+                    out->f.width  = 0;
+                    out->f.height = 0;
+                }
+            }
+            if ( pv->list_buffer == NULL )
+            {
+                pv->list_buffer = pv->last_buffer = out;
+            }
+            else
+            {
+                pv->last_buffer->next = out;
+            }
+            while (pv->last_buffer && pv->last_buffer->next)
+            {
+                pv->last_buffer = pv->last_buffer->next;
+            }
+        }
+        else if ( has_subtitle )
+        {
+            hb_buffer_close( &pv->list_pass_buffer );
+            pv->list_pass_buffer = NULL;
+        }
+        if ( has_subtitle )
+        {
+            avsubtitle_free(&subtitle);
+        }
+    } while (avp.size > 0);
+
+    *buf_out = pv->list_buffer;
+    pv->list_buffer = NULL;
+    return HB_WORK_OK;
+}
+
+static void decsubClose( hb_work_object_t * w )
+{
+    hb_work_private_t * pv = w->private_data;
+    avcodec_flush_buffers( pv->context );
+    avcodec_close( pv->context );
+}
+
+hb_work_object_t hb_decpgssub =
+{
+    WORK_DECPGSSUB,
+    "PGS decoder",
+    decsubInit,
+    decsubWork,
+    decsubClose
+};
index b633e78048d36aa0f9c5d6eff56ffff9c59e7d0c..43f2aefd90ed1e0a32f339abdd7f950b0fcafe07 100644 (file)
@@ -49,6 +49,7 @@ struct hb_work_private_s
     uint8_t       chromaU[4];
     uint8_t       chromaV[4];
     uint8_t       alpha[4];
+    uint8_t       palette_set;
 };
 
 static hb_buffer_t * Decode( hb_work_object_t * );
@@ -64,18 +65,23 @@ int decsubInit( hb_work_object_t * w, hb_job_t * job )
     pv->pts = 0;
     
     // Warn if the input color palette is empty
-    int paletteEmpty = 1;
-    int i;
-    for (i=0; i<16; i++)
+    pv->palette_set = w->subtitle->palette_set;
+    if ( pv->palette_set )
     {
-        if (w->subtitle->palette[i])
+        // Make sure the entries in the palette are not all 0
+        pv->palette_set = 0;
+        int i;
+        for (i=0; i<16; i++)
         {
-            paletteEmpty = 0;
-            break;
+            if (w->subtitle->palette[i])
+            {
+                pv->palette_set = 1;
+                break;
+            }
         }
     }
-    if (paletteEmpty) {
-        hb_log( "decvobsub: input color palette is empty; not demuxed properly?" );
+    if (!pv->palette_set) {
+        hb_log( "decvobsub: input color palette is empty!" );
     }
 
     return 0;
index 2ed6ef3e56c3e2a8191404f54f0061318683f943..0292078052c87ecd0e8fec809b46ad8ec49ffe15 100644 (file)
@@ -77,6 +77,7 @@ hb_filter_object_t hb_filter_deinterlace =
 {
     .id            = HB_FILTER_DEINTERLACE,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Deinterlace (ffmpeg or yadif/mcdeint)",
     .settings      = NULL,
     .init          = hb_deinterlace_init,
index dfc58863d53ec481e9ba8a37f2dce60e26af7251..48addf8e92f17771e5129d4276d5042e08e6c793 100644 (file)
@@ -46,6 +46,7 @@ hb_filter_object_t hb_filter_denoise =
 {
     .id            = HB_FILTER_DENOISE,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Denoise (hqdn3d)",
     .settings      = NULL,
     .init          = hb_denoise_init,
index 0437730f2689e80ae5082e69a65633e27e113741..0ec02303a13ebd96b1d426b57d4b055381c84fce 100644 (file)
@@ -98,6 +98,7 @@ hb_filter_object_t hb_filter_detelecine =
 {
     .id            = HB_FILTER_DETELECINE,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Detelecine (pullup)",
     .settings      = NULL,
     .init          = hb_detelecine_init,
index 338dd12d1432ca43afb9c7d51afc85df7fc1a0a9..f2e0ffeb3dc1f8448f2326b88b9a9a6c6992a096 100644 (file)
@@ -496,12 +496,16 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
         subtitle->format = PICTURESUB;
         subtitle->source = VOBSUB;
         subtitle->config.dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
+        subtitle->stream_type = 0xbd;
+        subtitle->substream_type = 0x20 + position;
+        subtitle->codec = WORK_DECVOBSUB;
 
         subtitle->type = lang_extension;
         
         memcpy( subtitle->palette,
             vts->vts_pgcit->pgci_srp[pgc_id-1].pgc->palette,
             16 * sizeof( uint32_t ) );
+        subtitle->palette_set = 1;
 
         switch( lang_extension )
         {  
index 52d062b0632d06b67e960a14f69e76b63861de41..8b356e188d896f20e7a06c9fd59a315ba7839e4f 100644 (file)
@@ -646,12 +646,16 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
         subtitle->format = PICTURESUB;
         subtitle->source = VOBSUB;
         subtitle->config.dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
+        subtitle->stream_type = 0xbd;
+        subtitle->substream_type = 0x20 + position;
+        subtitle->codec = WORK_DECVOBSUB;
 
         subtitle->type = lang_extension;
         
         memcpy( subtitle->palette,
             ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
             16 * sizeof( uint32_t ) );
+        subtitle->palette_set = 1;
 
         switch( lang_extension )
         {  
index 4a44d4343213b4fc65762f20ffd2cbbd0f07ad68..089639d6d98b141e2458db84a6f4d45b17fd909b 100644 (file)
@@ -164,7 +164,6 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
         lavc_opts = hb_encopts_to_dict( job->advanced_opts, job->vcodec );
     }
     /* iterate through lavc_opts and have avutil parse the options for us */
-    int ret;
     AVDictionary * av_opts = NULL;
     hb_dict_entry_t * entry = NULL;
     while( ( entry = hb_dict_next( lavc_opts, entry ) ) )
index 1dda37578fb3cde8bed699e5af609afb92eb4e2a..1b3b1c8b0ac00d1003f766413f0059f38c07a208 100644 (file)
@@ -459,6 +459,7 @@ hb_handle_t * hb_init( int verbose, int update_check )
     hb_register( &hb_decutf8sub );
     hb_register( &hb_dectx3gsub );
     hb_register( &hb_decssasub );
+    hb_register( &hb_decpgssub );
        hb_register( &hb_encavcodec );
        hb_register( &hb_encx264 );
     hb_register( &hb_enctheora );
@@ -1244,6 +1245,7 @@ void hb_add_filter( hb_job_t * job, hb_filter_object_t * filter, const char * se
             else if( f->id == filter->id )
             {
                 // Don't allow the same filter to be added twice
+                hb_filter_close( &filter );
                 return;
             }
         }
@@ -1569,7 +1571,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
         {
             subtitle = hb_list_item( title->list_subtitle, i );
             if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
-                subtitle->source == VOBSUB )
+                hb_subtitle_can_force( subtitle->source ) )
             {
                 /*
                  * Matched subtitle language with audio language, so
index 31b5492ad70eb903a22a79de1f96e254c8278e1e..5912139d5b46ad0d09e827b17233cffc3993f1fe 100644 (file)
@@ -155,7 +155,8 @@ hb_dict_t * hb_encopts_to_dict( const char * encopts, int encoder )
     hb_dict_t * dict = NULL;
     if( encopts && *encopts )
     {
-        char *cur_opt, *opts_start, *name, *value;
+        char *cur_opt, *opts_start, *value;
+        const char *name;
         dict = hb_dict_init( 10 );
         if( !dict )
             return NULL;
index 0ae63924a96dcb192a2f67751bb211a4384175a6..0d6ee27768a15092d758a922001c4f68c5ba7773 100644 (file)
@@ -395,7 +395,8 @@ enum
     WORK_ENC_CA_HAAC,
     WORK_ENCAVCODEC_AUDIO,
     WORK_MUX,
-    WORK_READER
+    WORK_READER,
+    WORK_DECPGSSUB
 };
 
 extern hb_filter_object_t hb_filter_detelecine;
index 1bed15c4900688801b65db3820a15b4cb88f7663..1140bc5b065dc220abb2025500fbea901c12476d 100644 (file)
@@ -322,9 +322,9 @@ static int MKVInit( hb_mux_object_t * m )
             continue;
 
         memset(track, 0, sizeof(mk_TrackConfig));
-        switch (subtitle->format)
+        switch (subtitle->source)
         {
-            case PICTURESUB:
+            case VOBSUB:
                 track->codecID = MK_SUBTITLE_VOBSUB;
                 for (j = 0; j < 16; j++)
                     rgb[j] = hb_yuv2rgb(subtitle->palette[j]);
@@ -338,16 +338,20 @@ static int MKVInit( hb_mux_object_t * m )
                 track->codecPrivate = subidx;
                 track->codecPrivateSize = len + 1;
                 break;
-            case TEXTSUB:
-                if (subtitle->source == SSASUB)
-                {
-                    track->codecID = MK_SUBTITLE_SSA;
-                    need_fonts = 1;
-                    track->codecPrivate = subtitle->extradata;
-                    track->codecPrivateSize = subtitle->extradata_size;
-                }
-                else
-                    track->codecID = MK_SUBTITLE_UTF8;
+            case PGSSUB:
+                track->codecID = "S_HDMV/PGS";
+                break;
+            case SSASUB:
+                track->codecID = MK_SUBTITLE_SSA;
+                need_fonts = 1;
+                track->codecPrivate = subtitle->extradata;
+                track->codecPrivateSize = subtitle->extradata_size;
+                break;
+            case CC608SUB:
+            case CC708SUB:
+            case UTF8SUB:
+            case TX3GSUB:
+                track->codecID = MK_SUBTITLE_UTF8;
                 break;
             default:
                 continue;
index bd3564be3437c925751a9ee73bedabdb7f8b8fab..6ccbaede3775699f31a1d90a69651dad267be414 100644 (file)
@@ -611,9 +611,7 @@ void hb_cond_wait( hb_cond_t * c, hb_lock_t * lock )
 void hb_clock_gettime( struct timespec *tp )
 {
     struct timeval tv;
-    time_t sec;
 
-    sec = time( NULL );
     gettimeofday( &tv, NULL );
     tp->tv_sec = tv.tv_sec;
     tp->tv_nsec = tv.tv_usec * 1000;
index 8707bd3d2da1a01b47aff427d85229fcbe419c1e..40eaba5fea4006f0fe9a085ec430edb9001fcd14 100644 (file)
@@ -38,6 +38,16 @@ static int ssa_work( hb_filter_object_t * filter,
 static void ssa_close( hb_filter_object_t * filter );
 
 
+// PGS
+static int pgssub_init ( hb_filter_object_t * filter, hb_filter_init_t * init );
+
+static int pgssub_work ( hb_filter_object_t * filter,
+                      hb_buffer_t ** buf_in,
+                      hb_buffer_t ** buf_out );
+
+static void pgssub_close( hb_filter_object_t * filter );
+
+
 // Entry points
 static int hb_rendersub_init( hb_filter_object_t * filter,
                                  hb_filter_init_t * init );
@@ -52,6 +62,7 @@ hb_filter_object_t hb_filter_render_sub =
 {
     .id            = HB_FILTER_RENDER_SUB,
     .enforce_order = 1,
+    .init_index    = 1,
     .name          = "Subtitle renderer",
     .settings      = NULL,
     .init          = hb_rendersub_init,
@@ -80,16 +91,15 @@ static void blend( hb_buffer_t *dst, hb_buffer_t *src, int left, int top )
     }
 
     ww = src->f.width;
-    if( left + src->f.width > dst->f.width )
+    if( src->f.width - x0 > dst->f.width - left )
     {
-        ww = dst->f.width - ( left + src->f.width );
+        ww = dst->f.width - left + x0;
     }
     hh = src->f.height;
-    if( top + src->f.height > dst->f.height )
+    if( src->f.height - y0 > dst->f.height - top )
     {
-        hh = dst->f.height - ( top + src->f.height );
+        hh = dst->f.height - top + y0;
     }
-
     // Blend luma
     for( yy = y0; yy < hh; yy++ )
     {
@@ -116,6 +126,7 @@ static void blend( hb_buffer_t *dst, hb_buffer_t *src, int left, int top )
         hshift = 1;
     if( dst->plane[1].width < dst->plane[0].width )
         wshift = 1;
+
     for( yy = y0 >> hshift; yy < hh >> hshift; yy++ )
     {
         u_in = src->plane[1].data + yy * src->plane[1].stride;
@@ -224,13 +235,14 @@ static void ApplyVOBSubs( hb_filter_private_t * pv, hb_buffer_t * buf )
     int ii;
     hb_buffer_t * sub;
 
-    for( ii = 0; ii < hb_list_count( pv->sub_list ); ii++ )
+    for( ii = 0; ii < hb_list_count( pv->sub_list ); )
     {
         sub = hb_list_item( pv->sub_list, ii );
         if( sub->s.stop <= buf->s.start )
         {
             // Subtitle stop is in the past, delete it
             hb_list_rem( pv->sub_list, sub );
+            hb_buffer_close( &sub );
         }
         else if( sub->s.start <= buf->s.start )
         {
@@ -241,6 +253,7 @@ static void ApplyVOBSubs( hb_filter_private_t * pv, hb_buffer_t * buf )
                 ApplySub( pv, buf, sub );
                 sub = sub->next;
             }
+            ii++;
         }
         else
         {
@@ -530,6 +543,116 @@ static int ssa_work( hb_filter_object_t * filter,
     return HB_FILTER_OK;
 }
 
+static void ApplyPGSSubs( hb_filter_private_t * pv, hb_buffer_t * buf )
+{
+    int index;
+    hb_buffer_t * old_sub;
+    hb_buffer_t * sub;
+
+    // Each PGS subtitle supersedes anything that preceded it.
+    // Find the active subtitle (if there is one), and delete
+    // everything before it.
+    for( index = hb_list_count( pv->sub_list ) - 1; index > 0; index-- )
+    {
+        sub = hb_list_item( pv->sub_list, index);
+        if ( sub->s.start <= buf->s.start )
+        {
+            while ( index > 0 )
+            {
+                old_sub = hb_list_item( pv->sub_list, index - 1);
+                hb_list_rem( pv->sub_list, old_sub );
+                hb_buffer_close( &old_sub );
+                index--;
+            }
+        }
+    }
+
+    // Some PGS subtitles have no content and only serve to clear
+    // the screen. If any of these are at the front of our list,
+    // we can now get rid of them.
+    while ( hb_list_count( pv->sub_list ) > 0 )
+    {
+        sub = hb_list_item( pv->sub_list, 0 );
+        if (sub->f.width != 0 && sub->f.height != 0)
+            break;
+
+        hb_list_rem( pv->sub_list, sub );
+        hb_buffer_close( &sub );
+    }
+
+    // Check to see if there's an active subtitle, and apply it.
+    if ( hb_list_count( pv->sub_list ) > 0)
+    {
+        sub = hb_list_item( pv->sub_list, 0 );
+        if ( sub->s.start <= buf->s.start )
+        {
+            while ( sub )
+            {
+                ApplySub( pv, buf, sub );
+                sub = sub->sub;
+            }
+        }
+    }
+}
+
+static int pgssub_init( hb_filter_object_t * filter,
+                        hb_filter_init_t * init )
+{
+    hb_filter_private_t * pv = filter->private_data;
+
+    // PGS render filter has no settings
+    memcpy( pv->crop, init->crop, sizeof( int[4] ) );
+
+    pv->sub_list = hb_list_init();
+
+    return 0;
+}
+
+static void pgssub_close( hb_filter_object_t * filter )
+{
+    hb_filter_private_t * pv = filter->private_data;
+
+    if ( !pv )
+    {
+        return;
+    }
+
+    if ( pv->sub_list )
+        hb_list_empty( &pv->sub_list );
+
+    free( pv );
+    filter->private_data = NULL;
+}
+
+static int pgssub_work( hb_filter_object_t * filter,
+                        hb_buffer_t ** buf_in,
+                        hb_buffer_t ** buf_out)
+{
+    hb_filter_private_t * pv = filter->private_data;
+    hb_buffer_t * in = *buf_in;
+    hb_buffer_t * sub;
+
+    if ( in->size <= 0 )
+    {
+        *buf_in = NULL;
+        *buf_out = in;
+        return HB_FILTER_DONE;
+    }
+
+    // Get any pending subtitles and add them to the active
+    // subtitle list
+    while ( ( sub = hb_fifo_get( filter->subtitle->fifo_out ) ) )
+    {
+        hb_list_add( pv->sub_list, sub );
+    }
+
+    ApplyPGSSubs( pv, in );
+    *buf_in = NULL;
+    *buf_out = in;
+
+    return HB_FILTER_OK;
+}
+
 static int hb_rendersub_init( hb_filter_object_t * filter,
                                  hb_filter_init_t * init )
 {
@@ -568,6 +691,11 @@ static int hb_rendersub_init( hb_filter_object_t * filter,
             return ssa_init( filter, init );
         } break;
 
+        case PGSSUB:
+        {
+            return pgssub_init( filter, init );
+        } break;
+
         default:
         {
             hb_log("rendersub: unsupported subtitle format %d", pv->type );
@@ -593,6 +721,11 @@ static int hb_rendersub_work( hb_filter_object_t * filter,
             return ssa_work( filter, buf_in, buf_out );
         } break;
 
+        case PGSSUB:
+        {
+            return pgssub_work( filter, buf_in, buf_out );
+        } break;
+
         default:
         {
             hb_error("rendersub: unsupported subtitle format %d", pv->type );
@@ -616,6 +749,11 @@ static void hb_rendersub_close( hb_filter_object_t * filter )
             ssa_close( filter );
         } break;
 
+        case PGSSUB:
+        {
+            pgssub_close( filter );
+        } break;
+
         default:
         {
             hb_error("rendersub: unsupported subtitle format %d", pv->type );
index 5f9558764e09b981cf39b400892caa745c8930f0..a96e6927d8ac2a127fee7c494f883955c2b80eb0 100644 (file)
@@ -46,6 +46,7 @@ hb_filter_object_t hb_filter_rotate =
 {
     .id            = HB_FILTER_ROTATE,
     .enforce_order = 0,
+    .init_index    = 2,
     .name          = "Rotate (rotate & flip image axes)",
     .settings      = NULL,
     .init          = hb_rotate_init,
index 1ad8659b7643ca014dc39aa459ef2f5bcca88b96..a3e6e1832eacf6fbf4aa3ec52bdcbcf82ba1704c 100644 (file)
@@ -237,7 +237,7 @@ static void ScanFunc( void * _data )
             for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
             {
                 hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, j );
-                if ( subtitle->source == VOBSUB )
+                if ( subtitle->source == VOBSUB || subtitle->source == PGSSUB )
                 {
                     subtitle->width = title->width;
                     subtitle->height = title->height;
index 2c7c4f9a5ec263e6c390f855cfdc5daedd14a2a8..7961eebfbe5ff913ffaf77d2e65d12f5600b64f3 100644 (file)
  * U - Unknown (to be determined by further processing)
  * A - Audio
  * V - Video
+ * S - Subtitle
  * P - PCR
  */
-typedef enum { N, U, A, V, P } kind_t;
+typedef enum { N, U, A, V, P, S } kind_t;
 typedef struct {
     kind_t kind; /* not handled / unknown / audio / video */
     int codec;          /* HB worker object id of codec */
@@ -82,7 +83,7 @@ static const stream2codec_t st2codec[256] = {
 
     st(0x8a, A, HB_ACODEC_DCA,     0,              "DTS"),
 
-    st(0x90, N, 0,                 0,              "PGS Subtitle"),
+    st(0x90, S, WORK_DECPGSSUB,    0,              "PGS Subtitle"),
     // 0x91 can be AC3 or BD Interactive Graphics Stream.
     st(0x91, U, 0,                 0,              "AC3/IGS"),
     st(0x92, N, 0,                 0,              "Subtitle"),
@@ -253,6 +254,7 @@ static int64_t pes_timestamp( const uint8_t *pes );
 static int hb_ts_stream_init(hb_stream_t *stream);
 static hb_buffer_t * hb_ts_stream_decode(hb_stream_t *stream);
 static void hb_init_audio_list(hb_stream_t *stream, hb_title_t *title);
+static void hb_init_subtitle_list(hb_stream_t *stream, hb_title_t *title);
 static int hb_ts_stream_find_pids(hb_stream_t *stream);
 
 static void hb_ps_stream_init(hb_stream_t *stream);
@@ -947,6 +949,15 @@ hb_stream_t * hb_bd_stream_open( hb_title_t *title )
         update_ts_streams( d, pid, stream_id_ext, stream_type, A, NULL );
     }
 
+    hb_subtitle_t * subtitle;
+    for ( ii = 0; ( subtitle = hb_list_item( title->list_subtitle, ii ) ); ++ii )
+    {
+        pid = subtitle->id & 0xFFFF;
+        stream_type = subtitle->stream_type;
+
+        update_ts_streams( d, pid, 0, stream_type, S, NULL );
+    }
+
     // When scanning, title->job == NULL.  We don't need to wait for
     // a PCR when scanning. In fact, it trips us up on the first
     // preview of every title since we would have to read quite a
@@ -1035,6 +1046,7 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream, hb_title_t * title)
     // - For program streams read the first 4MB and take every unique
     //   audio stream we find.
     hb_init_audio_list(stream, title);
+    hb_init_subtitle_list(stream, title);
 
     // set the video id, codec & muxer
     int idx = pes_index_of_video( stream );
@@ -2022,6 +2034,119 @@ static void set_audio_description(
               "%s", lang->iso639_2);
 }
 
+// Sort specifies the index in the audio list where you would
+// like sorted items to begin.
+static void pes_add_subtitle_to_title(
+    hb_stream_t *stream,
+    int         idx,
+    hb_title_t  *title,
+    int         sort)
+{
+    hb_pes_stream_t *pes = &stream->pes.list[idx];
+
+    // Sort by id when adding to the list
+    // This assures that they are always displayed in the same order
+    int id = get_id( pes );
+    int i;
+    hb_subtitle_t *tmp = NULL;
+
+    int count = hb_list_count( title->list_subtitle );
+
+    // Don't add the same audio twice.  Search for audio.
+    for ( i = 0; i < count; i++ )
+    {
+        tmp = hb_list_item( title->list_subtitle, i );
+        if ( id == tmp->id )
+            return;
+    }
+
+    hb_subtitle_t *subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
+    iso639_lang_t * lang;
+
+    subtitle->track = idx;
+    subtitle->id = id;
+    lang = lang_for_code( pes->lang_code );
+    snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
+              strlen(lang->native_name) ? lang->native_name : lang->eng_name);
+    snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
+              lang->iso639_2);
+
+    switch ( pes->codec )
+    {
+        case WORK_DECPGSSUB:
+            subtitle->source = PGSSUB;
+            subtitle->format = PICTURESUB;
+            subtitle->config.dest = RENDERSUB;
+            break;
+        case WORK_DECVOBSUB:
+            subtitle->source = VOBSUB;
+            subtitle->format = PICTURESUB;
+            subtitle->config.dest = RENDERSUB;
+            break;
+        default:
+            // Unrecognized, don't add to list
+            hb_log("unregonized subtitle!");
+            free( subtitle );
+            return;
+    }
+    subtitle->reg_desc = stream->reg_desc;
+    subtitle->stream_type = pes->stream_type;
+    subtitle->substream_type = pes->stream_id_ext;
+    subtitle->codec = pes->codec;
+
+    // Create a default palette since vob files do not include the
+    // vobsub palette.
+    if ( subtitle->source == VOBSUB )
+    {
+        subtitle->palette[0] = 0x108080;
+        subtitle->palette[1] = 0x108080;
+        subtitle->palette[2] = 0x108080;
+        subtitle->palette[3] = 0xbff000;
+
+        subtitle->palette[4] = 0xbff000;
+        subtitle->palette[5] = 0x108080;
+        subtitle->palette[6] = 0x108080;
+        subtitle->palette[7] = 0x108080;
+
+        subtitle->palette[8] = 0xbff000;
+        subtitle->palette[9] = 0x108080;
+        subtitle->palette[10] = 0x108080;
+        subtitle->palette[11] = 0x108080;
+
+        subtitle->palette[12] = 0x108080;
+        subtitle->palette[13] = 0xbff000;
+        subtitle->palette[14] = 0x108080;
+        subtitle->palette[15] = 0x108080;
+    }
+
+    hb_log("stream id 0x%x (type 0x%x substream 0x%x) subtitle 0x%x",
+           pes->stream_id, pes->stream_type, pes->stream_id_ext, subtitle->id);
+
+    // Search for the sort position
+    if ( sort >= 0 )
+    {
+        sort = sort < count ? sort : count;
+        for ( i = sort; i < count; i++ )
+        {
+            tmp = hb_list_item( title->list_subtitle, i );
+            int sid = tmp->id & 0xffff;
+            int ssid = tmp->id >> 16;
+            if ( pes->stream_id < sid )
+                break;
+            else if ( pes->stream_id <= sid &&
+                      pes->stream_id_ext <= ssid )
+            {
+                break;
+            }
+        }
+        hb_list_insert( title->list_subtitle, i, subtitle );
+    }
+    else
+    {
+        hb_list_add( title->list_subtitle, subtitle );
+    }
+}
+
 // Sort specifies the index in the audio list where you would
 // like sorted items to begin.
 static void pes_add_audio_to_title(
@@ -2090,6 +2215,42 @@ static void pes_add_audio_to_title(
     }
 }
 
+static void hb_init_subtitle_list(hb_stream_t *stream, hb_title_t *title)
+{
+    int ii;
+    int map_idx;
+    int largest = -1;
+
+    // First add all that were found in a map.
+    for ( map_idx = 0; 1; map_idx++ )
+    {
+        for ( ii = 0; ii < stream->pes.count; ii++ )
+        {
+            if ( stream->pes.list[ii].stream_kind == S )
+            {
+                if ( stream->pes.list[ii].map_idx == map_idx )
+                {
+                    pes_add_subtitle_to_title( stream, ii, title, -1 );
+                }
+                if ( stream->pes.list[ii].map_idx > largest )
+                    largest = stream->pes.list[ii].map_idx;
+            }
+        }
+        if ( map_idx > largest )
+            break;
+    }
+
+    int count = hb_list_count( title->list_audio );
+    // Now add the reset.  Sort them by stream id.
+    for ( ii = 0; ii < stream->pes.count; ii++ )
+    {
+        if ( stream->pes.list[ii].stream_kind == S )
+        {
+            pes_add_subtitle_to_title( stream, ii, title, count );
+        }
+    }
+}
+
 static void hb_init_audio_list(hb_stream_t *stream, hb_title_t *title)
 {
     int ii;
@@ -2206,6 +2367,19 @@ static int hb_ts_stream_init(hb_stream_t *stream)
                         stream->ts.list[i].is_pcr ? " (PCR)" : "");
             }
         }
+        hb_log("    Subtitle PIDS : ");
+        for (i = 0; i < stream->ts.count; i++)
+        {
+            if ( ts_stream_kind( stream, i ) == S )
+            {
+                hb_log( "      0x%x type %s (0x%x)%s",
+                        stream->ts.list[i].pid,
+                        stream_type_name2(stream,
+                                &stream->pes.list[stream->ts.list[i].pes_list]),
+                        ts_stream_type( stream, i ),
+                        stream->ts.list[i].is_pcr ? " (PCR)" : "");
+            }
+        }
         hb_log("    Other PIDS : ");
         for (i = 0; i < stream->ts.count; i++)
         {
@@ -2281,6 +2455,19 @@ static void hb_ps_stream_init(hb_stream_t *stream)
                         stream->pes.list[i].stream_type );
             }
         }
+        hb_log("    Subtitle Streams : ");
+        for (i = 0; i < stream->pes.count; i++)
+        {
+            if ( stream->pes.list[i].stream_kind == S )
+            {
+                hb_log( "      0x%x-0x%x type %s (0x%x)",
+                        stream->pes.list[i].stream_id,
+                        stream->pes.list[i].stream_id_ext,
+                        stream_type_name2(stream,
+                                         &stream->pes.list[i]),
+                        stream->pes.list[i].stream_type );
+            }
+        }
         hb_log("    Other Streams : ");
         for (i = 0; i < stream->pes.count; i++)
         {
@@ -3728,10 +3915,10 @@ static void hb_ps_stream_find_streams(hb_stream_t *stream)
                 // Check dvd substream id
                 if ( ssid >= 0x20 && ssid <= 0x37 )
                 {
-                    // Skip dvd subtitles
                     int idx = update_ps_streams( stream, pes_info.stream_id,
                                             pes_info.bd_substream_id, 0, -1 );
-                    stream->pes.list[idx].stream_kind = N;
+                    stream->pes.list[idx].stream_kind = S;
+                    stream->pes.list[idx].codec = WORK_DECVOBSUB;
                     strncpy(stream->pes.list[idx].codec_name, 
                             "DVD Subtitle", 80);
                     continue;
@@ -4122,6 +4309,7 @@ static void hb_ts_resolve_pid_types(hb_stream_t *stream)
         // stype == 0 indicates a type not in st2codec table
         if ( stype != 0 &&
              ( ts_stream_kind( stream, ii ) == A ||
+               ts_stream_kind( stream, ii ) == S ||
                ts_stream_kind( stream, ii ) == V ) )
         {
             // Assuming there are no substreams.
@@ -4203,6 +4391,7 @@ static void hb_ps_resolve_stream_types(hb_stream_t *stream)
         // stype == 0 indicates a type not in st2codec table
         if ( stype != 0 &&
              ( stream->pes.list[ii].stream_kind == A ||
+               stream->pes.list[ii].stream_kind == S ||
                stream->pes.list[ii].stream_kind == V ) )
         {
             stream->pes.list[ii].codec = st2codec[stype].codec;
@@ -5049,6 +5238,7 @@ static int ffmpeg_parse_vobsub_extradata_mkv( AVCodecContext *codec, hb_subtitle
         int i;
         for (i=0; i<16; i++)
             subtitle->palette[i] = hb_rgb2yuv(rgb[i]);
+        subtitle->palette_set = 1;
         return 0;
     }
     else
@@ -5072,6 +5262,7 @@ static int ffmpeg_parse_vobsub_extradata_mp4( AVCodecContext *codec, hb_subtitle
             codec->extradata[j+1] << 16 |   // Y
             codec->extradata[j+2] << 8  |   // Cb
             codec->extradata[j+3] << 0;     // Cr
+        subtitle->palette_set = 1;
     }
     if (codec->width <= 0 || codec->height <= 0)
     {
@@ -5113,6 +5304,7 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
             subtitle->format = PICTURESUB;
             subtitle->source = VOBSUB;
             subtitle->config.dest = RENDERSUB;  // By default render (burn-in) the VOBSUB.
+            subtitle->codec = WORK_DECVOBSUB;
             if ( ffmpeg_parse_vobsub_extradata( codec, subtitle ) )
                 hb_log( "add_ffmpeg_subtitle: malformed extradata for VOB subtitle track; "
                         "subtitle colors likely to be wrong" );
@@ -5121,16 +5313,25 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
             subtitle->format = TEXTSUB;
             subtitle->source = UTF8SUB;
             subtitle->config.dest = PASSTHRUSUB;
+            subtitle->codec = WORK_DECUTF8SUB;
             break;
         case CODEC_ID_MOV_TEXT: // TX3G
             subtitle->format = TEXTSUB;
             subtitle->source = TX3GSUB;
             subtitle->config.dest = PASSTHRUSUB;
+            subtitle->codec = WORK_DECTX3GSUB;
             break;
         case CODEC_ID_SSA:
             subtitle->format = TEXTSUB;
             subtitle->source = SSASUB;
             subtitle->config.dest = PASSTHRUSUB;
+            subtitle->codec = WORK_DECSSASUB;
+            break;
+        case CODEC_ID_HDMV_PGS_SUBTITLE:
+            subtitle->format = PICTURESUB;
+            subtitle->source = PGSSUB;
+            subtitle->config.dest = RENDERSUB;
+            subtitle->codec = WORK_DECPGSSUB;
             break;
         default:
             hb_log( "add_ffmpeg_subtitle: unknown subtitle stream type: 0x%x", (int) codec->codec_id );
index c9a4eebe65a88cf70030877135e1774a701bee8f..c76cc45d26ff19af19055e440f77946614cf9cc1 100644 (file)
@@ -69,10 +69,6 @@ typedef struct
     uint64_t   st_counts[4];
     uint64_t   st_dates[4];
     uint64_t   st_first;
-    
-    /* Subtitles */
-    hb_buffer_t * sub_list;   /* list of subtitles to be passed thru or rendered */
-    hb_buffer_t * sub_tail;   /* list of subtitles to be passed thru or rendered */
 } hb_sync_video_t;
 
 struct hb_work_private_s
index 9c3e2e2a8ee8e9155c75806aabce3c92d168d76b..7c70c21d4b01bdbb6c1b7911fb2128740ea7e389 100644 (file)
@@ -46,6 +46,7 @@ hb_filter_object_t hb_filter_vfr =
 {
     .id            = HB_FILTER_VFR,
     .enforce_order = 1,
+    .init_index    = 0,
     .name          = "Framerate Shaper",
     .settings      = NULL,
     .init          = hb_vfr_init,
index f9d7bf6569cf358518e171eef808719c4aeb2705..eab4db82153445b72487478ab7d99c738d13c163 100644 (file)
@@ -390,17 +390,20 @@ void hb_display_job_info( hb_job_t * job )
             {
                 /* For SRT, print offset and charset too */
                 hb_log( " * subtitle track %i, %s (id 0x%x) %s [%s] -> %s%s, offset: %"PRId64", charset: %s",
-                        subtitle->track, subtitle->lang, subtitle->id, "Text", "SRT", "Pass-Through",
+                        subtitle->out_track, subtitle->lang, subtitle->id,
+                        "Text", "SRT", "Pass-Through",
                         subtitle->config.default_track ? ", Default" : "",
                         subtitle->config.offset, subtitle->config.src_codeset );
             }
             else
             {
-                hb_log( " * subtitle track %i, %s (id 0x%x) %s [%s] -> %s%s%s", subtitle->track, subtitle->lang, subtitle->id,
+                hb_log( " * subtitle track %i, %s (id 0x%x) %s [%s] -> %s%s%s",
+                        subtitle->out_track, subtitle->lang, subtitle->id,
                         subtitle->format == PICTURESUB ? "Picture" : "Text",
                         hb_subsource_name( subtitle->source ),
                         job->indepth_scan ? "Foreign Audio Search" :
-                        subtitle->config.dest == RENDERSUB ? "Render/Burn in" : "Pass-Through",
+                            subtitle->config.dest == RENDERSUB ?
+                                "Render/Burn in" : "Pass-Through",
                         subtitle->config.force ? ", Forced Only" : "",
                         subtitle->config.default_track ? ", Default" : "" );
             }
@@ -489,6 +492,46 @@ void correct_framerate( hb_job_t * job )
     interjob->vrate_base = job->vrate_base;
 }
 
+void hb_filter_init_next( hb_list_t * list, int *score, int *ret_pos )
+{
+    int count = hb_list_count( list );
+    int pos = *ret_pos + 1;
+    int ii = 0;
+    if ( pos == 0 )
+    {
+        hb_filter_object_t * filter = hb_list_item( list, pos );
+        if ( filter->init_index == *score )
+        {
+            *ret_pos = pos;
+            return;
+        }
+        pos++;
+    }
+    while (1)
+    {
+        if ( pos == count )
+        {
+            pos = 0;
+            (*score)++;
+        }
+        hb_filter_object_t * filter = hb_list_item( list, pos );
+        if ( filter->init_index == *score )
+        {
+            *ret_pos = pos;
+            return;
+        }
+        pos++;
+        ii++;
+        if (ii > count)
+        {
+            // This is an error that should never happen
+            hb_error("internal error during filter initialization");
+            *ret_pos = -1;
+            return;
+        }
+    }
+}
+
 /**
  * Job initialization rountine.
  * Initializes fifos.
@@ -529,11 +572,139 @@ static void do_job( hb_job_t * job )
 
     hb_log( "starting job" );
 
+    /*
+     * Look for the scanned subtitle in the existing subtitle list
+     * select_subtitle implies that we did a scan.
+     */
+    if ( !job->indepth_scan && interjob->select_subtitle &&
+         ( job->pass == 0 || job->pass == 2 ) )
+    {
+        /*
+         * Disable forced subtitles if we didn't find any in the scan
+         * so that we display normal subtitles instead.
+         */
+        if( interjob->select_subtitle->config.force && 
+            interjob->select_subtitle->forced_hits == 0 )
+        {
+            interjob->select_subtitle->config.force = 0;
+        }
+        for( i=0; i < hb_list_count(title->list_subtitle); i++ )
+        {
+            subtitle =  hb_list_item( title->list_subtitle, i );
+
+            if( subtitle )
+            {
+                /*
+                * Remove the scanned subtitle from the subtitle list if
+                * it would result in an identical duplicate subtitle track
+                * or an emty track (forced and no forced hits).
+                */
+                if( ( interjob->select_subtitle->id == subtitle->id ) &&
+                    ( ( interjob->select_subtitle->forced_hits == 0 &&
+                        subtitle->config.force ) ||
+                    ( subtitle->config.force == interjob->select_subtitle->config.force ) ) )
+                {
+                    *subtitle = *(interjob->select_subtitle);
+                    free( interjob->select_subtitle );
+                    interjob->select_subtitle = NULL;
+                    break;
+                }
+            }
+        }
+
+        if( interjob->select_subtitle )
+        {
+            /*
+             * Its not in the existing list
+             *
+             * Must be second pass of a two pass with subtitle scan enabled, so
+             * add the subtitle that we found on the first pass for use in this
+             * pass.
+             */
+            hb_list_add( title->list_subtitle, interjob->select_subtitle );
+            interjob->select_subtitle = NULL;
+        }
+    }
+
+    if ( !job->indepth_scan )
+    {
+        // Sanitize subtitles
+        uint8_t one_burned = 0;
+        for( i=0; i < hb_list_count(title->list_subtitle); )
+        {
+            subtitle =  hb_list_item( title->list_subtitle, i );
+
+            if ( subtitle->config.dest == RENDERSUB )
+            {
+                if ( one_burned )
+                {
+                    if ( !hb_subtitle_can_pass(subtitle->source, job->mux) )
+                    {
+                        hb_log( "More than one subtitle burn-in requested, dropping track %d.", i );
+                        hb_list_rem( title->list_subtitle, subtitle );
+                        free( subtitle );
+                        continue;
+                    }
+                    else
+                    {
+                        hb_log( "More than one subtitle burn-in requested.  Changing track %d to soft subtitle.", i );
+                        subtitle->config.dest = PASSTHRUSUB;
+                    }
+                }
+                else if ( !hb_subtitle_can_burn(subtitle->source) )
+                {
+                    hb_log( "Subtitle burn-in requested and input track can not be rendered.  Changing track %d to soft subtitle.", i );
+                    subtitle->config.dest = PASSTHRUSUB;
+                }
+                else
+                {
+                    one_burned = 1;
+                }
+            }
+
+            if ( subtitle->config.dest == PASSTHRUSUB &&
+                 !hb_subtitle_can_pass(subtitle->source, job->mux) )
+            {
+                if ( !one_burned )
+                {
+                    hb_log( "Subtitle pass-thru requested and input track is not compatible with container.  Changing track %d to burned-in subtitle.", i );
+                    subtitle->config.dest = RENDERSUB;
+                    subtitle->config.default_track = 0;
+                    one_burned = 1;
+                }
+                else
+                {
+                    hb_log( "Subtitle pass-thru requested and input track is not compatible with container.  One track already burned, dropping track %d.", i );
+                    hb_list_rem( title->list_subtitle, subtitle );
+                    free( subtitle );
+                    continue;
+                }
+            }
+            /* Adjust output track number, in case we removed one.
+             * Output tracks sadly still need to be in sequential order.
+             * Note: out.track starts at 1, i starts at 0 */
+            subtitle->out_track = ++i;
+        }
+        if ( one_burned )
+        {
+            hb_filter_object_t * filter;
+
+            // Add subtitle rendering filter
+            // Note that if the filter is already in the filter chain, this
+            // has no effect. Note also that this means the front-end is
+            // not required to add the subtitle rendering filter since
+            // we will always try to do it here.
+            filter = hb_filter_init(HB_FILTER_RENDER_SUB);
+            hb_add_filter( job, filter, NULL );
+        }
+    }
+
     // Filters have an effect on settings.
     // So initialize the filters and update the job.
     if( job->list_filter && hb_list_count( job->list_filter ) )
     {
         hb_filter_init_t init;
+        int pos = -1, score = 0;
 
         init.job = job;
         init.pix_fmt = PIX_FMT_YUV420P;
@@ -547,7 +718,19 @@ static void do_job( hb_job_t * job )
         init.cfr = 0;
         for( i = 0; i < hb_list_count( job->list_filter ); i++ )
         {
-            hb_filter_object_t * filter = hb_list_item( job->list_filter, i );
+            // Some filters need to be initialized in a different order
+            // than they are executed in the pipeline.  e.g. rendersub
+            // needs to be initialized after cropscale so that it knows
+            // the crop settings, but it needs to be executed before
+            // cropscale. so hb_filter_init_next() finds returns the
+            // position of filters in initialization order.
+            hb_filter_init_next( job->list_filter, &score, &pos );
+            if( pos == -1)
+            {
+                // This is an error that should never happen!
+                break;
+            }
+            hb_filter_object_t * filter = hb_list_item( job->list_filter, pos );
             if( filter->init( filter, &init ) )
             {
                 hb_log( "Failure to initialise filter '%s', disabling",
@@ -847,60 +1030,6 @@ static void do_job( hb_job_t * job )
     w->fifo_in  = job->fifo_mpeg2;
     w->fifo_out = job->fifo_raw;
 
-    /*
-     * Look for the scanned subtitle in the existing subtitle list
-     * select_subtitle implies that we did a scan.
-     */
-    if ( !job->indepth_scan && interjob->select_subtitle &&
-         ( job->pass == 0 || job->pass == 2 ) )
-    {
-        /*
-         * Disable forced subtitles if we didn't find any in the scan
-         * so that we display normal subtitles instead.
-         */
-        if( interjob->select_subtitle->config.force && 
-            interjob->select_subtitle->forced_hits == 0 )
-        {
-            interjob->select_subtitle->config.force = 0;
-        }
-        for( i=0; i < hb_list_count(title->list_subtitle); i++ )
-        {
-            subtitle =  hb_list_item( title->list_subtitle, i );
-
-            if( subtitle )
-            {
-                /*
-                * Remove the scanned subtitle from the subtitle list if
-                * it would result in an identical duplicate subtitle track
-                * or an emty track (forced and no forced hits).
-                */
-                if( ( interjob->select_subtitle->id == subtitle->id ) &&
-                    ( ( interjob->select_subtitle->forced_hits == 0 &&
-                        subtitle->config.force ) ||
-                    ( subtitle->config.force == interjob->select_subtitle->config.force ) ) )
-                {
-                    *subtitle = *(interjob->select_subtitle);
-                    free( interjob->select_subtitle );
-                    interjob->select_subtitle = NULL;
-                    break;
-                }
-            }
-        }
-
-        if( interjob->select_subtitle )
-        {
-            /*
-             * Its not in the existing list
-             *
-             * Must be second pass of a two pass with subtitle scan enabled, so
-             * add the subtitle that we found on the first pass for use in this
-             * pass.
-             */
-            hb_list_add( title->list_subtitle, interjob->select_subtitle );
-            interjob->select_subtitle = NULL;
-        }
-    }
-
     for( i=0; i < hb_list_count(title->list_subtitle); i++ )
     {
         subtitle =  hb_list_item( title->list_subtitle, i );
@@ -920,60 +1049,17 @@ static void do_job( hb_job_t * job )
             subtitle->fifo_sync = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
             subtitle->fifo_out  = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
 
-            if( (!job->indepth_scan || job->select_subtitle_config.force) && 
-                subtitle->source == VOBSUB ) {
-                /*
-                 * Don't add threads for subtitles when we are scanning, unless
-                 * looking for forced subtitles.
-                 */
-                w = hb_get_work( WORK_DECVOBSUB );
-                w->fifo_in  = subtitle->fifo_in;
-                w->fifo_out = subtitle->fifo_raw;
-                w->subtitle = subtitle;
-                hb_list_add( job->list_work, w );
-            }
-
-            if( !job->indepth_scan && subtitle->source == CC608SUB )
-            {
-                w = hb_get_work( WORK_DECCC608 );
-                w->fifo_in  = subtitle->fifo_in;
-                w->fifo_out = subtitle->fifo_raw;
-                hb_list_add( job->list_work, w );
-            }
-
-            if( !job->indepth_scan && subtitle->source == SRTSUB )
-            {
-                w = hb_get_work( WORK_DECSRTSUB );
-                w->fifo_in  = subtitle->fifo_in;
-                w->fifo_out = subtitle->fifo_raw;
-                w->subtitle = subtitle;
-                hb_list_add( job->list_work, w );
-            }
-            
-            if( !job->indepth_scan && subtitle->source == UTF8SUB )
-            {
-                w = hb_get_work( WORK_DECUTF8SUB );
-                w->fifo_in  = subtitle->fifo_in;
-                w->fifo_out = subtitle->fifo_raw;
-                hb_list_add( job->list_work, w );
-            }
-            
-            if( !job->indepth_scan && subtitle->source == TX3GSUB )
+            if( job->indepth_scan && 
+                !( job->select_subtitle_config.force &&
+                   hb_subtitle_can_force( subtitle->source ) ) )
             {
-                w = hb_get_work( WORK_DECTX3GSUB );
-                w->fifo_in  = subtitle->fifo_in;
-                w->fifo_out = subtitle->fifo_raw;
-                hb_list_add( job->list_work, w );
-            }
-            
-            if( !job->indepth_scan && subtitle->source == SSASUB )
-            {
-                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 );
+                continue;
             }
+            w = hb_get_work( subtitle->codec );
+            w->fifo_in = subtitle->fifo_in;
+            w->fifo_out = subtitle->fifo_raw;
+            w->subtitle = subtitle;
+            hb_list_add( job->list_work, w );
         }
     }
 
index 53a64b9d68a0c78c89a994c4071207635d1517f4..88a146ae05a13eb9bb2d5e616ade32766f1c209a 100644 (file)
@@ -3185,28 +3185,6 @@ bool one_burned = FALSE;
             }
             else
             {
-                
-                /* for the actual source tracks, we must subtract the non source entries so 
-                 * that the menu index matches the source subtitle_list index for convenience */
-                if (i == 0)
-                {
-                    /* for the first track, the source tracks start at menu index 2 ( None is 0,
-                     * Foreign Language Search is 1) so subtract 2 */
-                    subtitle = subtitle - 2;
-                }
-                else
-                {
-                    /* for all other tracks, the source tracks start at menu index 1 (None is 0)
-                     * so subtract 1. */
-                    
-                    subtitle = subtitle - 1;
-                }
-                
-                /* We are setting a source subtitle so access the source subtitle info */  
-                hb_subtitle_t * subt;
-                
-                subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle);
-                
                 /* if we are getting the subtitles from an external srt file */
                 if ([[tempObject objectForKey:@"subtitleSourceTrackType"] isEqualToString:@"SRT"])
                 {
@@ -3225,35 +3203,48 @@ bool one_burned = FALSE;
                     sub_config.default_track = def;
                     
                     hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]);
+                    continue;
                 }
                 
-                if (subt != NULL)
+                /* for the actual source tracks, we must subtract the non source entries so 
+                 * that the menu index matches the source subtitle_list index for convenience */
+                if( i == 0 )
+                {
+                    /* for the first track, the source tracks start at menu index 2 ( None is 0,
+                     * Foreign Language Search is 1) so subtract 2 */
+                    subtitle = subtitle - 2;
+                }
+                else
+                {
+                    /* for all other tracks, the source tracks start at menu index 1 (None is 0)
+                     * so subtract 1. */
+                    subtitle = subtitle - 1;
+                }
+                
+                /* We are setting a source subtitle so access the source subtitle info */  
+                hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle );
+                
+                if( subt != NULL )
                 {
                     hb_subtitle_config_t sub_config = subt->config;
                     
-                    if ( !burned && subt->format == PICTURESUB )
+                    if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) )
                     {
                         sub_config.dest = PASSTHRUSUB;
                     }
-                    else if ( burned && subt->format == PICTURESUB )
+                    else if( hb_subtitle_can_burn( subt->source ) )
                     {
                         // Only allow one subtitle to be burned into the video
-                        if (one_burned)
+                        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 );
-                }   
-                
+                }
             }
         }
         i++;
@@ -3724,28 +3715,6 @@ bool one_burned = FALSE;
             }
             else
             {
-                
-                /* for the actual source tracks, we must subtract the non source entries so 
-                 * that the menu index matches the source subtitle_list index for convenience */
-                if (i == 0)
-                {
-                    /* for the first track, the source tracks start at menu index 2 ( None is 0,
-                     * Foreign Language Search is 1) so subtract 2 */
-                    subtitle = subtitle - 2;
-                }
-                else
-                {
-                    /* for all other tracks, the source tracks start at menu index 1 (None is 0)
-                     * so subtract 1. */
-                    
-                    subtitle = subtitle - 1;
-                }
-                
-                /* We are setting a source subtitle so access the source subtitle info */  
-                hb_subtitle_t * subt;
-                
-                subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle);
-                
                 /* if we are getting the subtitles from an external srt file */
                 if ([[tempObject objectForKey:@"subtitleSourceTrackType"] isEqualToString:@"SRT"])
                 {
@@ -3764,36 +3733,48 @@ bool one_burned = FALSE;
                     sub_config.default_track = def;
                     
                     hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]);
+                    continue;
+                }
+                
+                /* for the actual source tracks, we must subtract the non source entries so 
+                 * that the menu index matches the source subtitle_list index for convenience */
+                if( i == 0 )
+                {
+                    /* for the first track, the source tracks start at menu index 2 ( None is 0,
+                     * Foreign Language Search is 1) so subtract 2 */
+                    subtitle = subtitle - 2;
+                }
+                else
+                {
+                    /* for all other tracks, the source tracks start at menu index 1 (None is 0)
+                     * so subtract 1. */
+                    subtitle = subtitle - 1;
                 }
                 
+                /* We are setting a source subtitle so access the source subtitle info */  
+                hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle );
                 
-                if (subt != NULL)
+                if( subt != NULL )
                 {
                     hb_subtitle_config_t sub_config = subt->config;
                     
-                    if ( !burned && subt->format == PICTURESUB )
+                    if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) )
                     {
                         sub_config.dest = PASSTHRUSUB;
                     }
-                    else if ( burned  )
+                    else if( hb_subtitle_can_burn( subt->source ) )
                     {
                         // Only allow one subtitle to be burned into the video
-                        if (one_burned)
+                        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 );
-                }   
-                
+                }
             }
         }
         i++;
index 1d0c45ae6aa9c928e902dbda2a4ddfe9fc397195..f84749303c0a180f85acfa23e52f1ed801469b45 100644 (file)
@@ -3,18 +3,10 @@
    This file is part of the HandBrake source code.
    Homepage: <http://handbrake.fr/>.
    It may be used under the terms of the GNU General Public License. */
-//
 
 #import "HBSubtitles.h"
 #include "hb.h"
 
-
-
-
-
-
-
-
 @implementation HBSubtitles
 - (id)init 
 {
                 subtitle = (hb_subtitle_t *) hb_list_item( fTitle->list_subtitle, i );
                 sub_config = subtitle->config;
                 
-                int canBeBurnedIn = subtitle->source == VOBSUB || subtitle->source == SSASUB;
-                int supportsForcedFlags = subtitle->source == VOBSUB;
+                int canBeBurnedIn = hb_subtitle_can_burn( subtitle->source );
+                int supportsForcedFlags = hb_subtitle_can_force( subtitle->source );
                 
                 /* create a dictionary of source subtitle information to store in our array */
                 NSMutableDictionary *newSubtitleSourceTrack = [[NSMutableDictionary alloc] init];
                 [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:i] forKey:@"sourceTrackNum"];
                 /* Human-readable representation of subtitle->source */
                 NSString *subSourceName = [NSString stringWithUTF8String:hb_subsource_name( subtitle->source )];
-                NSString *bitmapOrText = subtitle->source == PICTURESUB ? @"Bitmap" : @"Text";
+                NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text";
                 /* Subtitle Source track name */
                 NSString *popupName = [NSString stringWithFormat:@"%d - %@ - (%@) (%@)",i,[NSString stringWithUTF8String:subtitle->lang],bitmapOrText,subSourceName];
                 [newSubtitleSourceTrack setObject:popupName forKey:@"sourceTrackName"];
          */
         if (container == HB_MUX_MP4 && [anObject intValue] != 0)
         {
-            if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] isEqualToString:[NSString stringWithUTF8String:hb_subsource_name( VOBSUB )]])
+            NSString *subtitleSourceTrackType = [[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"];
+            if ([subtitleSourceTrackType isEqualToString:[NSString stringWithUTF8String:hb_subsource_name( VOBSUB )]] ||
+                [subtitleSourceTrackType isEqualToString:[NSString stringWithUTF8String:hb_subsource_name( PGSSUB )]])
             {
                 /* lets see if there are currently any burned in subs specified */
                 NSEnumerator *enumerator = [subtitleArray objectEnumerator];
                     }
                 }
                 /* if we have no current vobsub set to burn it in ... burn it in by default */
-                if(!subtrackBurnedInFound)
+                if (!subtrackBurnedInFound)
                 {
                     [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackBurned"];
                     /* Burned In and Default are mutually exclusive */
index 504a3507dba39c7e332bab0df322434246abe71b..758dd0fa28b0610b0283097e88b7c335d0e4490a 100644 (file)
@@ -2229,11 +2229,10 @@ static int HandleEvents( hb_handle_t * h )
 
                         force = test_sub_list(subforce, i+1);
                         
-                        int supports_burn =
-                            ( subtitle->source == VOBSUB ) ||
-                            ( subtitle->source == SSASUB );
+                        int supports_burn = hb_subtitle_can_burn( subtitle->source );
                         
-                        if ( burn && supports_burn )
+                        if ( ( burn && supports_burn ) ||
+                             !hb_subtitle_can_pass( subtitle->source, mux ) )
                         {
                             // Only allow one subtitle to be burned into video
                             if ( sub_burned )