[MPlayer-dev-eng] [PATCH] some embedded subtitle cleanups

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Sun Nov 12 16:03:49 CET 2006


Hello,
On Sun, Nov 12, 2006 at 03:23:02PM +0100, Reimar D?ffinger wrote:
> this patch is a first step to cleanup subtitle stream handling by
> handling it more similar to other streams.
> Many more changes will be needed in the future, but we have to start
> somewhere.
> Okay to apply?

Fixed version, it also adds preliminary support for subtitles in these
files (that part is to be applied separately of course):
http://samples.mplayerhq.hu/mov/subtitles-embedded/subtitlemovie.mov
http://samples.mplayerhq.hu/sub/NeroMP4/unsupported-embedded-subs-2.mp4

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libmpdemux/demux_mkv.c
===================================================================
--- libmpdemux/demux_mkv.c	(revision 20861)
+++ libmpdemux/demux_mkv.c	(working copy)
@@ -1766,6 +1766,8 @@
 demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid);
 static int
 demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid);
+static int
+demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid);
 
 static void
 display_create_tracks (demuxer_t *demuxer)
@@ -1796,7 +1798,7 @@
           break;
         case MATROSKA_TRACK_SUBTITLE:
           type = "subtitles";
-          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
+          demux_mkv_open_sub(demuxer, mkv_d->tracks[i], sid);
           if (mkv_d->tracks[i]->name)
             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", sid, mkv_d->tracks[i]->name);
           mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, mkv_d->tracks[i]->language);
@@ -2408,18 +2410,18 @@
 #endif
 
 static int
-demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track)
+demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid)
 {
   if (track->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN)
     {
+      sh_sub_t *sh = new_sh_sub_sid(demuxer, track->tnum, sid);
       if ((track->subtitle_type == MATROSKA_SUBTYPE_VOBSUB) ||
           (track->subtitle_type == MATROSKA_SUBTYPE_SSA))
         {
           if (track->private_data != NULL)
             {
-              demuxer->sub->sh = malloc(sizeof(sh_sub_t));
-              if (demuxer->sub->sh != NULL)
-                memcpy(demuxer->sub->sh, &track->sh_sub, sizeof(sh_sub_t));
+              if (sh)
+                memcpy(sh, &track->sh_sub, sizeof(sh_sub_t));
             }
         }
     }
@@ -2680,7 +2682,7 @@
     track = demux_mkv_find_track_by_language (mkv_d, dvdsub_lang,
                                               MATROSKA_TRACK_SUBTITLE);
 
-  if (track && !demux_mkv_open_sub (demuxer, track))
+  if (track)
           {
             mp_msg (MSGT_DEMUX, MSGL_INFO,
                     MSGTR_MPDEMUX_MKV_WillDisplaySubtitleTrack, track->tnum);
Index: libmpdemux/demux_mov.c
===================================================================
--- libmpdemux/demux_mov.c	(revision 20861)
+++ libmpdemux/demux_mov.c	(working copy)
@@ -32,6 +32,9 @@
 
 #include "bswap.h"
 
+#include "libvo/sub.h"
+extern subtitle *vo_sub;
+
 #include "qtpalette.h"
 #include "parse_mp4.h" // .MP4 specific stuff
 
@@ -290,6 +293,7 @@
 }
 
 #define MOV_MAX_TRACKS 256
+#define MOV_MAX_SUBLEN 1024
 
 typedef struct {
     off_t moov_start;
@@ -300,6 +304,9 @@
     mov_track_t* tracks[MOV_MAX_TRACKS];
     int timescale; // movie timescale
     int duration;  // movie duration (in movie timescale units)
+    subtitle subs;
+    char subtext[MOV_MAX_SUBLEN + 1];
+    int current_sub;
 } mov_priv_t;
 
 #define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d))
@@ -312,6 +319,7 @@
     mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n");
     
     memset(priv,0,sizeof(mov_priv_t));
+    priv->current_sub = -1;
     
     while(1){
 	int i;
@@ -1285,6 +1293,11 @@
 		break;
 	    }
 	    case MOV_TRAK_GENERIC:
+		if (trak->fourcc == mmioFOURCC('m','p','4','s') ||
+		    trak->fourcc == mmioFOURCC('t','e','x','t')) {
+			sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db);
+			sh->type = (trak->fourcc == mmioFOURCC('m','p','4','s')) ? 'v' : 't';
+		} else
 		mp_msg(MSGT_DEMUX, MSGL_V, "Generic track - not completely understood! (id: %d)\n",
 		    trak->id);
 		/* XXX: Also this contains the FLASH data */
@@ -1918,6 +1931,15 @@
 	    demuxer->video->id=-2;
 	}
     }
+    if(demuxer->sub->id>=0){
+	sh_video_t* sh=demuxer->s_streams[demuxer->sub->id];
+	if(sh){
+	    demuxer->sub->sh=sh; sh->ds=demuxer->sub;
+	} else {
+	    mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected video stream (%d) does not exists\n",demuxer->video->id);
+	    demuxer->sub->id=-2;
+	}
+    }
 
     if(demuxer->video->id<0 && demuxer->audio->id<0) {
         /* No AV streams found. Try to find an MPEG stream. */
@@ -2115,6 +2137,41 @@
     
     ++trak->pos;
 
+    if (demuxer->sub->id >= 0) {
+      int samplenr = 0;
+      trak = priv->tracks[demuxer->sub->id];
+      while (samplenr < trak->samples_size) {
+        double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
+        if (subpts >= pts) break;
+        samplenr++;
+      }
+      samplenr--;
+      if (samplenr < 0)
+        vo_sub = NULL;
+      else if (samplenr != priv->current_sub) {
+        sh_sub_t *sh = demuxer->sub->sh;
+        off_t pos = trak->samples[samplenr].pos;
+        int len = trak->samples[samplenr].size;
+        double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
+        stream_seek(demuxer->stream, pos);
+        if (sh->type == 'v')
+          ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0);
+        else {
+          stream_skip(demuxer->stream, 2); // size
+          len -= 2;
+          if (len < 0) len = 0;
+          if (len > MOV_MAX_SUBLEN) len = MOV_MAX_SUBLEN;
+          stream_read(demuxer->stream, priv->subtext, len);
+          priv->subtext[len] = 0;
+          priv->subs.lines = 1;
+          priv->subs.text[0] = &priv->subtext;
+          vo_sub = &priv->subs;
+        }
+        priv->current_sub = samplenr;
+      }
+      vo_osd_changed (OSDTYPE_SUBTITLE);
+    }
+
     return 1;
     
 }
Index: libmpdemux/demux_mpg.c
===================================================================
--- libmpdemux/demux_mpg.c	(revision 20861)
+++ libmpdemux/demux_mpg.c	(working copy)
@@ -298,7 +298,7 @@
 
         if(!demux->s_streams[aid]){
             mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
-            demux->s_streams[aid]=1;
+            new_sh_sub(demux, aid);
         }
 
         if(demux->sub->id > -1)
Index: libmpdemux/stheader.h
===================================================================
--- libmpdemux/stheader.h	(revision 20861)
+++ libmpdemux/stheader.h	(working copy)
@@ -95,6 +95,8 @@
 sh_audio_t* new_sh_audio_aid(demuxer_t *demuxer,int id,int aid);
 #define new_sh_video(d, i) new_sh_video_vid(d, i, i)
 sh_video_t* new_sh_video_vid(demuxer_t *demuxer,int id,int vid);
+#define new_sh_sub(d, i) new_sh_sub_sid(d, i, i)
+sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid);
 void free_sh_audio(demuxer_t *demuxer, int id);
 void free_sh_video(sh_video_t *sh);
 
Index: libmpdemux/demuxer.c
===================================================================
--- libmpdemux/demuxer.c	(revision 20861)
+++ libmpdemux/demuxer.c	(working copy)
@@ -201,6 +201,23 @@
   return d;
 }
 
+sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) {
+  if (id > MAX_S_STREAMS - 1 || id < 0) {
+    mp_msg(MSGT_DEMUXER,MSGL_WARN,"Requested sub stream id overflow (%d > %d)\n",
+           id, MAX_S_STREAMS);
+    return NULL;
+  }
+  if (demuxer->s_streams[id])
+    mp_msg(MSGT_DEMUXER, MSGL_WARN, "Sub stream %i redefined\n", id);
+  else {
+    sh_sub_t *sh = calloc(1, sizeof(sh_sub_t));
+    demuxer->s_streams[id] = sh;
+    sh->sid = sid;
+    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
+  }
+  return demuxer->s_streams[id];
+}
+
 sh_audio_t* new_sh_audio_aid(demuxer_t *demuxer,int id,int aid){
     if(id > MAX_A_STREAMS-1 || id < 0)
     {
Index: libmpdemux/demuxer.h
===================================================================
--- libmpdemux/demuxer.h	(revision 20861)
+++ libmpdemux/demuxer.h	(working copy)
@@ -138,10 +138,12 @@
 #ifdef USE_ASS
   ass_track_t* ass_track;  // for SSA/ASS streams (type == 'a')
 #endif
+  int sid;
 } sh_sub_t;
 
 #define MAX_A_STREAMS 256
 #define MAX_V_STREAMS 256
+#define MAX_S_STREAMS 32
 
 struct demuxer_st;
 
@@ -199,7 +201,7 @@
   // stream headers:
   void* a_streams[MAX_A_STREAMS]; // audio streams (sh_audio_t)
   void* v_streams[MAX_V_STREAMS]; // video sterams (sh_video_t)
-  char s_streams[32];   // dvd subtitles (flag)
+  void *s_streams[MAX_S_STREAMS];   // dvd subtitles (flag)
 
   demux_chapter_t* chapters;
   int num_chapters;


More information about the MPlayer-dev-eng mailing list