changeset 19643:f48d49b400cf

Add support for rendering matroska plaintext subtitles with libass.
author eugeni
date Sat, 02 Sep 2006 20:46:26 +0000
parents db2a522e319e
children 775ac4efed3c
files libass/ass_mp.c libass/ass_mp.h libmpdemux/demux_mkv.c
diffstat 3 files changed, 105 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/libass/ass_mp.c	Sat Sep 02 19:55:45 2006 +0000
+++ b/libass/ass_mp.c	Sat Sep 02 20:46:26 2006 +0000
@@ -2,6 +2,8 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "mp_msg.h"
+
 #include "ass.h"
 #include "ass_mp.h"
 
@@ -23,23 +25,13 @@
 extern double ass_internal_font_size_coeff; 
 extern void process_force_style(ass_track_t* track);
 
-/**
- * \brief Convert subdata to ass_track
- * \param subdata subtitles struct from subreader
- * \param fps video framerate
- * \return newly allocated ass_track, filled with subtitles from subdata
- */
-ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
+ass_track_t* ass_default_track() {
 	ass_track_t* track = ass_new_track();
 	ass_style_t* style;
-	ass_event_t* event;
-	subtitle* sub;
-	int sid, eid;
-	int i;
+	int sid;
 	double fs;
 
 	track->track_type = TRACK_TYPE_ASS;
-	track->name = subdata->filename ? strdup(subdata->filename) : 0;
 	track->Timer = 100.;
 	track->PlayResX = 384;
 	track->PlayResY = 288;
@@ -71,22 +63,44 @@
 	style->ScaleX = 1.;
 	style->ScaleY = 1.;
 
-	for (i = 0; i < subdata->sub_num; ++i) {
-		int len = 0, j;
-		char* p;
-		char* end;
-		sub = subdata->subtitles + i;
-		eid = ass_alloc_event(track);
-		event = track->events + eid;
+	return track;
+}
+
+static int check_duplicate_plaintext_event(ass_track_t* track)
+{
+	int i;
+	ass_event_t* evt = track->events + track->n_events - 1;
+
+	for (i = 0; i<track->n_events - 1; ++i) // ignoring last event, it is the one we are comparing with
+		if (track->events[i].Start == evt->Start &&
+		    track->events[i].Duration == evt->Duration &&
+		    strcmp(track->events[i].Text, evt->Text) == 0)
+			return 1;
+	return 0;
+}
 
-		event->Start = sub->start * 10;
-		event->Duration = (sub->end - sub->start) * 10;
-		if (!subdata->sub_uses_time) {
-			event->Start *= 100. / fps;
-			event->Duration *= 100. / fps;
-		}
+/**
+ * \brief Convert subtitle to ass_event_t for the given track
+ * \param ass_track_t track
+ * \param sub subtitle to convert
+ * \return event id
+ * note: assumes that subtitle is _not_ fps-based; caller must manually correct
+ *   Start and Duration in other case.
+ **/
+int ass_process_subtitle(ass_track_t* track, subtitle* sub)
+{
+        int eid;
+        ass_event_t* event;
+	int len = 0, j;
+	char* p;
+	char* end;
 
-		event->Style = sid;
+	eid = ass_alloc_event(track);
+	event = track->events + eid;
+
+	event->Start = sub->start * 10;
+	event->Duration = (sub->end - sub->start) * 10;
+	event->Style = 0;
 
 		for (j = 0; j < sub->lines; ++j)
 			len += sub->text[j] ? strlen(sub->text[j]) : 0;
@@ -107,6 +121,41 @@
 
 		p--; // remove last ' '
 		*p = 0;
+
+	if (check_duplicate_plaintext_event(track)) {
+		ass_free_event(track, eid);
+		track->n_events--;
+		return -1;
+	}
+
+	mp_msg(MSGT_GLOBAL, MSGL_V, "plaintext event at %" PRId64 ", +%" PRId64 ": %s  \n",
+			(int64_t)event->Start, (int64_t)event->Duration, event->Text);
+	
+	return eid;
+}
+
+
+/**
+ * \brief Convert subdata to ass_track
+ * \param subdata subtitles struct from subreader
+ * \param fps video framerate
+ * \return newly allocated ass_track, filled with subtitles from subdata
+ */
+ass_track_t* ass_read_subdata(sub_data* subdata, double fps) {
+	ass_track_t* track;
+	int i;
+
+	track = ass_default_track();
+	track->name = subdata->filename ? strdup(subdata->filename) : 0;
+
+	for (i = 0; i < subdata->sub_num; ++i) {
+		int eid = ass_process_subtitle(track, subdata->subtitles + i);
+		if (eid < 0)
+			continue;
+		if (!subdata->sub_uses_time) {
+			track->events[eid].Start *= 100. / fps;
+			track->events[eid].Duration *= 100. / fps;
+		}
 	}
 	process_force_style(track);
 	return track;
--- a/libass/ass_mp.h	Sat Sep 02 19:55:45 2006 +0000
+++ b/libass/ass_mp.h	Sat Sep 02 20:46:26 2006 +0000
@@ -12,6 +12,8 @@
 extern char **ass_force_style_list;
 extern int ass_use_margins;
 
+ass_track_t* ass_default_track();
+int ass_process_subtitle(ass_track_t* track, subtitle* sub);
 ass_track_t* ass_read_subdata(sub_data* subdata, double fps);
 
 #endif
--- a/libmpdemux/demux_mkv.c	Sat Sep 02 19:55:45 2006 +0000
+++ b/libmpdemux/demux_mkv.c	Sat Sep 02 20:46:26 2006 +0000
@@ -2323,10 +2323,14 @@
   for (i = 0; i < mkv_d->num_tracks; i++)
     {
       track = mkv_d->tracks[i];
-      if ((track->type != MATROSKA_TRACK_SUBTITLE) ||
-          (track->subtitle_type != MATROSKA_SUBTYPE_SSA))
+      if (track->type != MATROSKA_TRACK_SUBTITLE)
         continue;
 
+      track->sh_sub.type = 'a';
+
+      if (track->subtitle_type == MATROSKA_SUBTYPE_SSA)
+        {
+      track->sh_sub.ass_track = ass_new_track();
       size = track->private_size;
       m = demux_mkv_decode (track,track->private_data,&buffer,&size,2);
       if (buffer && m)
@@ -2335,9 +2339,12 @@
           track->private_data = buffer;
           track->private_size = size;
         }
-      track->sh_sub.type = 'a';
-      track->sh_sub.ass_track = ass_new_track();
       ass_process_codec_private(track->sh_sub.ass_track, track->private_data, track->private_size);
+        }
+      else
+        {
+          track->sh_sub.ass_track = ass_default_track();
+        }
     }
 }
 #endif
@@ -2812,6 +2819,9 @@
 }
 
 static void
+clear_subtitles(demuxer_t *demuxer, uint64_t timecode, int clear_all);
+
+static void
 handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block,
                  int64_t size, uint64_t block_duration, uint64_t timecode)
 {
@@ -2831,6 +2841,7 @@
     ass_process_chunk(track->sh_sub.ass_track, block, size, (long long)timecode, (long long)block_duration);
     return;
   }
+  clear_subtitles(demuxer, timecode, 1);
 #endif
 
   ptr1 = block;
@@ -2942,6 +2953,13 @@
   mkv_d->clear_subs_at[mkv_d->subs.lines++] = timecode + block_duration;
 
   sub_utf8 = 1;
+#ifdef USE_ASS
+  if (ass_enabled) {
+    mkv_d->subs.start = timecode / 10;
+    mkv_d->subs.end = (timecode + block_duration) / 10;
+    ass_process_subtitle(track->sh_sub.ass_track, &mkv_d->subs);
+  } else
+#endif
   vo_sub = &mkv_d->subs;
   vo_osd_changed (OSDTYPE_SUBTITLE);
 }
@@ -2958,6 +2976,9 @@
     {
       lines_cut = mkv_d->subs.lines;
       mkv_d->subs.lines = 0;
+#ifdef USE_ASS
+      if (!ass_enabled)
+#endif
       if (lines_cut)
         {
           vo_sub = &mkv_d->subs;
@@ -2981,6 +3002,9 @@
           lines_cut = 1;
         }
     }
+#ifdef USE_ASS
+  if (!ass_enabled)
+#endif
   if (lines_cut)
     {
       vo_sub = &mkv_d->subs;