# HG changeset patch # User eugeni # Date 1157229986 0 # Node ID f48d49b400cf3264dcdf440c3dcb0430ee38e1eb # Parent db2a522e319e91d8c435b7c0a78e9fc9577069ac Add support for rendering matroska plaintext subtitles with libass. diff -r db2a522e319e -r f48d49b400cf libass/ass_mp.c --- 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 #include +#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; in_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; diff -r db2a522e319e -r f48d49b400cf libass/ass_mp.h --- 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 diff -r db2a522e319e -r f48d49b400cf libmpdemux/demux_mkv.c --- 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;