[MPlayer-dev-eng] [PATCH] fix -novideo with subs (bug 1186)

Reimar Döffinger Reimar.Doeffinger at gmx.de
Sat Jun 20 17:27:45 CEST 2009


On Sat, Jun 20, 2009 at 04:06:30PM +0200, Reimar Döffinger wrote:
> On Sat, Jun 20, 2009 at 03:40:31PM +0200, Anton Khirnov wrote:
> > this patch (taken from
> > http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1186, credit goes to
> > unframed-gmail-com) fixes a segfault when using -novideo on a file with
> > subs.
> 
> Seems like not a good solution to me. It should ideally still be
> possible to select subtitles if no video is available, e.g. they
> could be printed onto the terminal.
> I admit I don't know how much effort that would be though.

I am not completely happy with it, and it breaks mencoder compilation,
but this patch can display subs for audio-only files.
-------------- next part --------------
Index: mp_osd.h
===================================================================
--- mp_osd.h	(revision 29374)
+++ mp_osd.h	(working copy)
@@ -11,6 +11,7 @@
 #define OSD_MSG_RADIO_CHANNEL           7
 /// Base id for messages generated from the commmand to property bridge.
 #define OSD_MSG_PROPERTY                0x100
+#define OSD_MSG_SUB_BASE                0x1000
 
 #define MAX_OSD_LEVEL 3
 #define MAX_TERM_OSD_LEVEL 1
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 29374)
+++ mplayer.c	(working copy)
@@ -1493,6 +1493,26 @@
                 name,ROUND(100*(val-min)/(max-min)));
 }
 
+/**
+ * \brief Display text subtitles on the OSD
+ */
+void set_osd_subtitle(subtitle *subs) {
+    int i;
+    vo_sub = subs;
+    vo_osd_changed(OSDTYPE_SUBTITLE);
+    if (!mpctx->sh_video) {
+        // reverse order, since newest set_osd_msg is displayed first
+        for (i = SUB_MAX_TEXT - 1; i >= 0; i--) {
+            if (!subs || i >= subs->lines || !subs->text[i])
+                rm_osd_msg(OSD_MSG_SUB_BASE + i);
+            else {
+                // HACK: currently display time for each sub line except the last is set to 2 seconds.
+                int display_time = i == subs->lines - 1 ? 180000 : 2000;
+                set_osd_msg(OSD_MSG_SUB_BASE + i, 1, display_time, "%s", subs->text[i]);
+            }
+        }
+    }
+}
 
 /**
  * \brief Update the OSD message line.
@@ -1753,7 +1773,7 @@
 	current_module = "decode video";
 	decoded_frame = decode_video(sh_video, start, in_size, drop_frame, pts);
 	if (decoded_frame) {
-	    update_subtitles(sh_video, mpctx->d_sub, 0);
+	    update_subtitles(sh_video, mpctx->sh_audio, mpctx->d_sub, 0);
 	    update_teletext(sh_video, mpctx->demuxer, 0);
 	    update_osd_msg();
 	    current_module = "filter video";
@@ -2276,7 +2296,7 @@
 	// video_read_frame can change fps (e.g. for ASF video)
 	vo_fps = sh_video->fps;
 	drop_frame = check_framedrop(frame_time);
-	update_subtitles(sh_video, mpctx->d_sub, 0);
+	update_subtitles(sh_video, mpctx->sh_audio, mpctx->d_sub, 0);
 	update_teletext(sh_video, mpctx->demuxer, 0);
 	update_osd_msg();
 	current_module = "decode_video";
@@ -2469,7 +2489,6 @@
 	// (which is used by at least vobsub and edl code below) may
 	// be completely wrong (probably 0).
 	mpctx->sh_video->pts = mpctx->d_video->pts;
-	update_subtitles(mpctx->sh_video, mpctx->d_sub, 1);
 	update_teletext(mpctx->sh_video, mpctx->demuxer, 1);
     }
 
@@ -2480,6 +2499,8 @@
 	mpctx->sh_audio->a_out_buffer_len = 0;
     }
 
+    update_subtitles(mpctx->sh_video, mpctx->sh_audio, mpctx->d_sub, 1);
+
     if (vo_vobsub && mpctx->sh_video) {
 	current_module = "seek_vobsub_reset";
 	vobsub_seek(vo_vobsub, mpctx->sh_video->pts);
@@ -3679,6 +3700,7 @@
 
   if(end_at.type == END_AT_TIME && end_at.pos < a_pos)
     mpctx->eof = PT_NEXT_ENTRY;
+  update_subtitles(mpctx->sh_video, mpctx->sh_audio, mpctx->d_sub, 0);
   update_osd_msg();
 
 } else {
Index: command.c
===================================================================
--- command.c	(revision 29375)
+++ command.c	(working copy)
@@ -1510,7 +1510,7 @@
 	d_sub->id = dvdsub_id;
     }
 #endif
-    update_subtitles(mpctx->sh_video, d_sub, 1);
+    update_subtitles(mpctx->sh_video, mpctx->sh_audio, d_sub, 1);
 
     return M_PROPERTY_OK;
 }
Index: mpcommon.c
===================================================================
--- mpcommon.c	(revision 29374)
+++ mpcommon.c	(working copy)
@@ -67,17 +67,19 @@
 }
 
 
-void update_subtitles(sh_video_t *sh_video, demux_stream_t *d_dvdsub, int reset)
+void update_subtitles(sh_video_t *sh_video, sh_audio_t *sh_audio, demux_stream_t *d_dvdsub, int reset)
 {
     unsigned char *packet=NULL;
     int len;
     char type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v';
     static subtitle subs;
+    double pts = 0;
+    if (sh_video || sh_audio)
+        pts = sh_video ? sh_video->pts : sh_audio->pts;
     if (reset) {
         sub_clear_text(&subs, MP_NOPTS_VALUE);
         if (vo_sub) {
-            vo_sub = NULL;
-            vo_osd_changed(OSDTYPE_SUBTITLE);
+            set_osd_subtitle(NULL);
         }
         if (vo_spudec) {
             spudec_reset(vo_spudec);
@@ -86,8 +88,7 @@
     }
     // find sub
     if (subdata) {
-        double pts = sh_video->pts;
-        if (sub_fps==0) sub_fps = sh_video->fps;
+        if (sub_fps==0) sub_fps = sh_video ? sh_video->fps : 20;
         current_module = "find_sub";
         if (pts > sub_last_pts || pts < sub_last_pts-1.0) {
             find_sub(subdata, (pts+sub_delay) *
@@ -110,11 +111,11 @@
             // Vobsub
             len = 0;
             if (vo_vobsub) {
-                if (sh_video->pts+sub_delay >= 0) {
-                    len = vobsub_get_packet(vo_vobsub, sh_video->pts+sub_delay,
+                if (pts+sub_delay >= 0) {
+                    len = vobsub_get_packet(vo_vobsub, pts+sub_delay,
                                             (void**)&packet, &timestamp);
                     if (len > 0) {
-                        timestamp -= (sh_video->pts + sub_delay - sh_video->timer)*90000;
+                        timestamp -= (pts + sub_delay - sh_video->timer)*90000;
                         mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,sh_video->pts,sh_video->timer,timestamp / 90000.0,timestamp);
                     }
                 }
@@ -127,14 +128,14 @@
                     // d_video->pts which would have been the simplest
                     // improvement doesn't work because mpeg specific hacks
                     // in video.c set d_video->pts to 0.
-                    float x = d_dvdsub->pts - sh_video->pts;
+                    float x = d_dvdsub->pts - pts;
                     if (x > -20 && x < 20) // prevent missing subs on pts reset
                         timestamp = 90000*(sh_video->timer + d_dvdsub->pts
-                                           + sub_delay - sh_video->pts);
+                                           + sub_delay - pts);
                     else timestamp = 90000*(sh_video->timer + sub_delay);
                     mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d  "
                            "v_pts=%5.3f  s_pts=%5.3f  ts=%d \n", len,
-                           sh_video->pts, d_dvdsub->pts, timestamp);
+                           pts, d_dvdsub->pts, timestamp);
                 }
             }
             if (len<=0 || !packet) break;
@@ -145,9 +146,8 @@
         if (spudec_changed(vo_spudec))
             vo_osd_changed(OSDTYPE_SPU);
     } else if (dvdsub_id >= 0 && (type == 't' || type == 'm' || type == 'a')) {
-        double curpts = sh_video->pts + sub_delay;
+        double curpts = pts + sub_delay;
         double endpts;
-        vo_sub = &subs;
         while (d_dvdsub->first) {
             double pts = ds_get_next_pts(d_dvdsub);
             if (pts > curpts)
@@ -169,7 +169,6 @@
                                       (long long)(pts*1000 + 0.5),
                                       (long long)((endpts-pts)*1000 + 0.5));
                 } else { // plaintext subs with libass
-                    vo_sub = NULL;
                     if (pts != MP_NOPTS_VALUE) {
                         if (endpts == MP_NOPTS_VALUE) endpts = pts + 3;
                         sub_clear_text(&subs, MP_NOPTS_VALUE);
@@ -197,11 +196,11 @@
                     packet = p;
                 }
                 sub_add_text(&subs, packet, len, endpts);
-                vo_osd_changed(OSDTYPE_SUBTITLE);
+                set_osd_subtitle(&subs);
             }
         }
         if (sub_clear_text(&subs, curpts))
-            vo_osd_changed(OSDTYPE_SUBTITLE);
+            set_osd_subtitle(&subs);
     }
     current_module=NULL;
 }
Index: mpcommon.h
===================================================================
--- mpcommon.h	(revision 29374)
+++ mpcommon.h	(working copy)
@@ -10,7 +10,7 @@
 extern subtitle *vo_sub_last;
 
 void print_version(const char* name);
-void update_subtitles(sh_video_t *sh_video, demux_stream_t *d_dvdsub, int reset);
+void update_subtitles(sh_video_t *sh_video, sh_audio_t *sh_audio, demux_stream_t *d_dvdsub, int reset);
 void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset);
 int select_audio(demuxer_t* demuxer, int audio_id, char* audio_lang);
 


More information about the MPlayer-dev-eng mailing list