[Mplayer-cvslog] CVS: main/libmpdemux matroska.h,1.6,1.7 demux_mkv.cpp,1.29,1.30
Moritz Bunkus CVS
mosu at mplayerhq.hu
Wed Sep 10 14:50:56 CEST 2003
Update of /cvsroot/mplayer/main/libmpdemux
In directory mail:/var/tmp.root/cvs-serv7625
Modified Files:
matroska.h demux_mkv.cpp
Log Message:
Support for SSA text subs in Matroska. Patch partially by Tristan <z80 at oceanfree.net>.
Index: matroska.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/matroska.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- matroska.h 10 Sep 2003 11:39:40 -0000 1.6
+++ matroska.h 10 Sep 2003 12:50:29 -0000 1.7
@@ -27,8 +27,8 @@
#define MKV_A_REALCOOK "A_REAL/COOK"
#define MKV_A_REALDNET "A_REAL/DNET"
#define MKV_A_REALSIPR "A_REAL/SIPR"
-#define MKV_A_QDMC "A_QDESIGNMUSIC"
-#define MKV_A_QDMC2 "A_QDESIGNMUSIC/V2"
+#define MKV_A_QDMC "A_QUICKTIME/QDMC"
+#define MKV_A_QDMC2 "A_QUICKTIME/QDM2"
#define MKV_V_MSCOMP "V_MS/VFW/FOURCC"
#define MKV_V_REALV10 "V_REAL/RV10"
@@ -43,5 +43,6 @@
#define MKV_S_TEXTASCII "S_TEXT/ASCII"
#define MKV_S_TEXTUTF8 "S_TEXT/UTF8"
+#define MKV_S_TEXTSSA "S_TEXT/SSA"
#endif /* __MATROSKA_H */
Index: demux_mkv.cpp
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_mkv.cpp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- demux_mkv.cpp 10 Sep 2003 11:39:40 -0000 1.29
+++ demux_mkv.cpp 10 Sep 2003 12:50:29 -0000 1.30
@@ -69,6 +69,9 @@
// default values for Matroska elements
#define MKVD_TIMECODESCALE 1000000 // 1000000 = 1ms
+#define MKV_SUBTYPE_TEXT 1
+#define MKV_SUBTYPE_SSA 2
+
class mpstream_io_callback: public IOCallback {
private:
stream_t *s;
@@ -187,9 +190,10 @@
mpstream_io_callback *in;
- uint64_t clear_subs_at;
+ uint64_t clear_subs_at[SUB_MAX_TEXT];
subtitle subs;
+ int subtitle_type;
EbmlStream *es;
EbmlElement *saved_l1, *saved_l2;
@@ -397,7 +401,7 @@
static void handle_subtitles(demuxer_t *d, KaxBlock *block, int64_t duration) {
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *)d->priv;
- int len, line, state;
+ int len, line, state, i;
char *s1, *s2, *buffer;
if (duration == -1) {
@@ -417,34 +421,83 @@
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;
- 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;
- s2 = mkv_d->subs.text[mkv_d->subs.lines];
- mkv_d->subs.lines++;
+
+ if (mkv_d->subtitle_type == MKV_SUBTYPE_SSA) {
+ /* 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 (i = 0; (i < 8) && (*s1 != 0); s1++)
+ if (*s1 == ',')
+ i++;
+
+ if (*s1 == 0) { // Broken line?
+ mkv_d->subs.lines--;
+ return;
+ }
+
+ /* Load text. */
+ while ((unsigned int)(s1 - buffer) < data.Size()) {
+ if ((*s1 == '{') && ((unsigned int)(s1 + 2 - buffer) < data.Size())) {
+ /* 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 == '<') // skip HTML tags
- state = 2;
- else if (*s1 == '>')
- state = 0;
- else if (state != 2) { // normal character
- state = 0;
- if ((s2 - mkv_d->subs.text[mkv_d->subs.lines - 1]) < 255) {
+ } else if (*s1 == '}' && state == 1)
+ state = 2;
+
+ if (state == 0) {
*s2 = *s1;
s2++;
+ if ((s2 - mkv_d->subs.text[mkv_d->subs.lines - 1]) >= 255)
+ break;
}
+ s1++;
+
+ if (state == 2)
+ state = 0;
}
- s1++;
- }
+ *s2 = 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;
+ }
+ } else if (*s1 == '<') // skip HTML tags
+ state = 2;
+ else if (*s1 == '>')
+ state = 0;
+ else if (state != 2) { // normal character
+ state = 0;
+ if ((s2 - mkv_d->subs.text[mkv_d->subs.lines - 1]) < 255) {
+ *s2 = *s1;
+ s2++;
+ }
+ }
+ s1++;
+ }
+
+ *s2 = 0;
+ }
#ifdef USE_ICONV
subcp_recode1(&mkv_d->subs);
@@ -453,8 +506,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) {
@@ -1837,7 +1890,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 {
@@ -1850,6 +1904,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_type = MKV_SUBTYPE_SSA;
+ else
+ mkv_d->subtitle_type = MKV_SUBTYPE_TEXT;
} else
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] File does not contain a "
"subtitle track with the id %u.\n", demuxer->sub->id);
@@ -1992,13 +2050,14 @@
demux_packet_t *dp;
demux_stream_t *ds;
mkv_demuxer_t *mkv_d;
- int upper_lvl_el, exit_loop, found_data, i;
+ int upper_lvl_el, exit_loop, found_data, i, linei, sl;
+ char *texttmp;
// Elements for different levels
EbmlElement *l0 = NULL, *l1 = NULL, *l2 = NULL, *l3 = NULL;
EbmlStream *es;
KaxBlock *block;
int64_t block_duration, block_bref, block_fref;
- bool use_this_block;
+ bool use_this_block, lines_cut;
float current_pts;
mkv_d = (mkv_demuxer_t *)d->priv;
@@ -2087,13 +2146,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;
+ lines_cut = false;
+ for (linei = 0; linei < mkv_d->subs.lines; linei++) {
+ if (mkv_d->clear_subs_at[linei] <=
+ (kblock->GlobalTimecode() / 1000000 - mkv_d->first_tc)) {
+ sl = linei;
+ 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--;
+ lines_cut = true;
+ }
+ if (lines_cut) {
+ vo_sub = &mkv_d->subs;
+ vo_osd_changed(OSDTYPE_SUBTITLE);
+ }
}
ds = NULL;
@@ -2424,7 +2496,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);
More information about the MPlayer-cvslog
mailing list