changeset 13126:b59e16a8dfc7

Support for subtitle switching in Matroska.
author mosu
date Tue, 24 Aug 2004 20:58:29 +0000
parents 69f13a4cbab9
children 957fc21fc10a
files libmpdemux/demux_mkv.c libmpdemux/matroska.h mplayer.c
diffstat 3 files changed, 139 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_mkv.c	Tue Aug 24 20:48:24 2004 +0000
+++ b/libmpdemux/demux_mkv.c	Tue Aug 24 20:58:29 2004 +0000
@@ -1973,6 +1973,46 @@
   return 0;
 }
 
+/** \brief Parse the private data for VobSub subtitle tracks.
+
+  This function tries to parse the private data for all VobSub tracks.
+  The private data contains the normal text from the original .idx file.
+  Things like the palette, subtitle dimensions and custom colors are
+  stored here.
+
+  \param demuxer The generic demuxer.
+*/
+static void
+demux_mkv_parse_vobsub_data (demuxer_t *demuxer)
+{
+  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
+  mkv_track_t *track;
+  int i, m, size;
+  uint8_t *buffer;
+
+  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_VOBSUB))
+        continue;
+
+      size = track->private_size;
+      m = demux_mkv_decode (track,track->private_data,&buffer,&size,2);
+      if (buffer && m)
+        {
+          free (track->private_data);
+          track->private_data = buffer;
+        }
+      if (!demux_mkv_parse_idx (track))
+        {
+          free (track->private_data);
+          track->private_data = NULL;
+          track->private_size = 0;
+        }
+    }
+}
+
 static int
 demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track)
 {
@@ -1980,15 +2020,7 @@
     {
       if (track->subtitle_type == MATROSKA_SUBTYPE_VOBSUB)
         {
-          int m, size = track->private_size;
-          uint8_t *buffer;
-          m = demux_mkv_decode (track,track->private_data,&buffer,&size,2);
-          if (buffer && m)
-            {
-              free (track->private_data);
-              track->private_data = buffer;
-            }
-          if (demux_mkv_parse_idx (track))
+          if (track->private_data != NULL)
             {
               demuxer->sub->sh = malloc(sizeof(mkv_sh_sub_t));
               if (demuxer->sub->sh != NULL)
@@ -2206,6 +2238,7 @@
       demuxer->audio->id = -2;
     }
 
+  demux_mkv_parse_vobsub_data (demuxer);
   /* DO NOT automatically select a subtitle track and behave like DVD */
   /* playback: only show subtitles if the user explicitely wants them. */
   track = NULL;
@@ -3122,4 +3155,66 @@
     }
 }
 
+/** \brief Return the number of subtitle tracks in the file.
+
+  \param demuxer The demuxer for which the number of subtitle tracks
+  should be returned.
+*/
+int
+demux_mkv_num_subs (demuxer_t *demuxer)
+{
+  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
+  int i, num;
+
+  num = 0;
+  for (i = 0; i < mkv_d->num_tracks; i++)
+    if ((mkv_d->tracks[i]->type == MATROSKA_TRACK_SUBTITLE) &&
+        (mkv_d->tracks[i]->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN))
+      num++;
+
+  return num;
+}
+
+/** \brief Change the current subtitle track and return its ID.
+
+  Changes the current subtitle track. If the new subtitle track is a
+  VobSub track then the SPU decoder will be re-initialized.
+
+  \param demuxer The demuxer whose subtitle track will be changed.
+  \param new_num The number of the new subtitle track. The number must be
+  between 0 and demux_mkv_num_subs - 1.
+
+  \returns The Matroska track number of the newly selected track.
+*/
+int
+demux_mkv_change_subs (demuxer_t *demuxer, int new_num)
+{
+  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
+  mkv_track_t *track;
+  int i, num;
+
+  num = 0;
+  track = NULL;
+  for (i = 0; i < mkv_d->num_tracks; i++)
+    {
+      if ((mkv_d->tracks[i]->type == MATROSKA_TRACK_SUBTITLE) &&
+          (mkv_d->tracks[i]->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN))
+        num++;
+      if (num == (new_num + 1))
+        {
+          track = mkv_d->tracks[i];
+          break;
+        }
+    }
+  if (track == NULL)
+    return -1;
+
+  if (demuxer->sub->sh == NULL)
+    demuxer->sub->sh = malloc(sizeof(mkv_sh_sub_t));
+  if (demuxer->sub->sh != NULL)
+    memcpy(demuxer->sub->sh, &track->sh_sub, sizeof(mkv_sh_sub_t));
+
+  return track->tnum;
+}
+
 #endif /* HAVE_MATROSKA */
--- a/libmpdemux/matroska.h	Tue Aug 24 20:48:24 2004 +0000
+++ b/libmpdemux/matroska.h	Tue Aug 24 20:58:29 2004 +0000
@@ -7,6 +7,8 @@
 #ifndef __MATROSKA_H
 #define __MATROSKA_H
 
+#include "demuxer.h"
+
 #define MKV_A_AAC_2MAIN  "A_AAC/MPEG2/MAIN"
 #define MKV_A_AAC_2LC    "A_AAC/MPEG2/LC"
 #define MKV_A_AAC_2SBR   "A_AAC/MPEG2/LC/SBR"
@@ -61,4 +63,7 @@
   int forced_subs_only;
 } mkv_sh_sub_t;
 
+int demux_mkv_num_subs(demuxer_t *);
+int demux_mkv_change_subs(demuxer_t *, int);
+
 #endif /* __MATROSKA_H */
--- a/mplayer.c	Tue Aug 24 20:48:24 2004 +0000
+++ b/mplayer.c	Tue Aug 24 20:58:29 2004 +0000
@@ -1590,7 +1590,7 @@
 demux_info_print(demuxer);
 
 //================== Read SUBTITLES (DVD & TEXT) ==========================
-if(vo_spudec==NULL && sh_video && stream->type==STREAMTYPE_DVD){
+if(vo_spudec==NULL && sh_video && (stream->type==STREAMTYPE_DVD || demuxer->type==DEMUXER_TYPE_MATROSKA)){
 
 if (spudec_ifo) {
   unsigned int palette[16], width, height;
@@ -3178,6 +3178,35 @@
 	d_dvdsub->id = demux_ogg_sub_id(new_id);
     }
 #endif
+#ifdef HAVE_MATROSKA
+    if (d_dvdsub && demuxer->type == DEMUXER_TYPE_MATROSKA) {
+      int new_id = dvdsub_id + 1;
+      if (dvdsub_id < 0)
+        new_id = 0;
+      if ((unsigned int) new_id >= demux_mkv_num_subs(demuxer))
+        new_id = -1;
+      if (new_id != dvdsub_id)
+        osd_show_vobsub_changed = sh_video->fps;
+      dvdsub_id = new_id;
+      d_dvdsub->id = demux_mkv_change_subs(demuxer, new_id);
+      if (d_dvdsub->id >= 0 && ((mkv_sh_sub_t *)d_dvdsub->sh)->type == 'v') {
+        mkv_sh_sub_t *mkv_sh_sub = (mkv_sh_sub_t *)d_dvdsub->sh;
+        if (vo_spudec != NULL)
+          spudec_free(vo_spudec);
+        vo_spudec =
+          spudec_new_scaled_vobsub(mkv_sh_sub->palette, mkv_sh_sub->colors,
+                                   mkv_sh_sub->custom_colors,
+                                   mkv_sh_sub->width,
+                                   mkv_sh_sub->height);
+        if (!forced_subs_only)
+          forced_subs_only = mkv_sh_sub->forced_subs_only;
+        if (vo_spudec) {
+          spudec_set_forced_subs_only(vo_spudec, forced_subs_only);
+          inited_flags |= INITED_SPUDEC;
+        }
+      }
+    }
+#endif
         break;
     case MP_CMD_SUB_FORCED_ONLY:
       if (vo_spudec) {