--- libmpdemux/demux_mkv.cpp 27 Aug 2003 13:08:40 -0000 1.28 +++ libmpdemux/demux_mkv.cpp 10 Sep 2003 02:36:41 -0000 @@ -182,9 +182,10 @@ mpstream_io_callback *in; - uint64_t clear_subs_at; + uint64_t clear_subs_at[SUB_MAX_TEXT]; subtitle subs; + int subtitle_ssa; EbmlStream *es; EbmlElement *saved_l1, *saved_l2; @@ -388,15 +389,59 @@ s1++; line = 0; - s2 = mkv_d->subs.text[0]; - mkv_d->subs.lines = 1; + mkv_d->subs.lines++; + s2 = mkv_d->subs.text[mkv_d->subs.lines - 1]; state = 0; + + if (mkv_d->subtitle_ssa == 1) { + /* Matroska's SSA format does not have timecodes embedded into + the SAA line. Timescodes are encoded into the blocks timecode + and duration. */ + + /* Find text section. */ + for(int i = 0; i < 8;) { + if(*s1 == ',') + i++; + s1++; + } + + /* Load text. */ + while ((unsigned int)(s1 - buffer) != data.Size()) { + if (*s1 == '{') { + /* Newline */ + if (*(s1 + 1) == '\\' && (*(s1 + 2) == 'N' || *(s1 + 2) == 'n')) { + mkv_d->clear_subs_at[mkv_d->subs.lines - 1] = + block->GlobalTimecode() / 1000000 - mkv_d->first_tc + duration; + + mkv_d->subs.lines++; + *s2 = 0; + s2 = mkv_d->subs.text[mkv_d->subs.lines - 1]; + } + state = 1; + } else if (*s1 == '}' && state == 1) { + state = 2; + } + + if (state == 0) { + *s2 = *s1; + s2++; + } + s1++; + + if (state == 2) { + state = 0; + } + } + *s2 = 0; + } else { while ((unsigned int)(s1 - buffer) != data.Size()) { if ((*s1 == '\n') || (*s1 == '\r')) { if (state == 0) { // normal char --> newline if (mkv_d->subs.lines == SUB_MAX_TEXT) break; *s2 = 0; + mkv_d->clear_subs_at[mkv_d->subs.lines - 1]= + block->GlobalTimecode() / 1000000 - mkv_d->first_tc + duration; s2 = mkv_d->subs.text[mkv_d->subs.lines]; mkv_d->subs.lines++; state = 1; @@ -416,6 +461,7 @@ } *s2 = 0; + } #ifdef USE_ICONV subcp_recode1(&mkv_d->subs); @@ -424,8 +470,8 @@ vo_sub = &mkv_d->subs; vo_osd_changed(OSDTYPE_SUBTITLE); - mkv_d->clear_subs_at = block->GlobalTimecode() / 1000000 - mkv_d->first_tc + - duration; + mkv_d->clear_subs_at[mkv_d->subs.lines - 1] = + block->GlobalTimecode() / 1000000 - mkv_d->first_tc + duration; } static mkv_track_t *new_mkv_track(mkv_demuxer_t *d) { @@ -1761,7 +1807,8 @@ track = find_track_by_language(mkv_d, dvdsub_lang, NULL); if (track) { if (strcmp(track->codec_id, MKV_S_TEXTASCII) && - strcmp(track->codec_id, MKV_S_TEXTUTF8)) + strcmp(track->codec_id, MKV_S_TEXTUTF8) && + strcmp(track->codec_id, MKV_S_TEXTSSA)) mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Subtitle type '%s' is not " "supported. Track will not be displayed.\n", track->codec_id); else { @@ -1774,6 +1821,10 @@ if (!strcmp(track->codec_id, MKV_S_TEXTUTF8)) sub_utf8 = 1; // Force UTF-8 conversion. + if (!strcmp(track->codec_id, MKV_S_TEXTSSA)) + mkv_d->subtitle_ssa = 1; + else + mkv_d->subtitle_ssa = 0; } else mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] File does not contain a " "subtitle track with the id %u.\n", demuxer->sub->id); @@ -2011,13 +2062,26 @@ if (kblock != NULL) { // Clear the subtitles if they're obsolete now. - if ((mkv_d->clear_subs_at > 0) && - (mkv_d->clear_subs_at <= - (kblock->GlobalTimecode() / 1000000 - mkv_d->first_tc))) { - mkv_d->subs.lines = 0; - vo_sub = &mkv_d->subs; - vo_osd_changed(OSDTYPE_SUBTITLE); - mkv_d->clear_subs_at = 0; + int linescut = 0; + for (int linei = 0; linei < mkv_d->subs.lines; linei++) { + if (mkv_d->clear_subs_at[linei] <= + (kblock->GlobalTimecode() / 1000000 - mkv_d->first_tc)) { + int sl = linei; + char *texttmp = mkv_d->subs.text[sl]; + while (sl < mkv_d->subs.lines) { + mkv_d->subs.text[sl] = mkv_d->subs.text[sl + 1]; + mkv_d->clear_subs_at[sl] = mkv_d->clear_subs_at[sl + 1]; + sl++; + } + mkv_d->subs.text[sl] = texttmp; + mkv_d->subs.lines--; + linei--; + linescut = 1; + } + if (linescut) { + vo_sub = &mkv_d->subs; + vo_osd_changed(OSDTYPE_SUBTITLE); + } } ds = NULL; @@ -2323,7 +2387,6 @@ mkv_d->subs.lines = 0; vo_sub = &mkv_d->subs; vo_osd_changed(OSDTYPE_SUBTITLE); - mkv_d->clear_subs_at = 0; if(demuxer->audio->sh != NULL) resync_audio_stream((sh_audio_t *)demuxer->audio->sh);