changeset 31612:7fc1f051a19f

Change global subtitle numbering scheme so that demuxers can "asynchronously" add subtitles during playback.
author reimar
date Sat, 10 Jul 2010 20:48:50 +0000
parents d8408f8f996b
children 55abf5e08172
files command.c mp_core.h mplayer.c
diffstat 3 files changed, 110 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/command.c	Sat Jul 10 18:53:08 2010 +0000
+++ b/command.c	Sat Jul 10 20:48:50 2010 +0000
@@ -98,19 +98,62 @@
            vo_dheight, vo_fs);
 }
 
-static int sub_source_by_pos(MPContext *mpctx, int pos)
+static void update_global_sub_size(MPContext *mpctx)
 {
-    int source = -1;
-    int top = -1;
+    int i;
+    int cnt = 0;
+
+    // update number of demuxer sub streams
+    for (i = 0; i < MAX_S_STREAMS; i++)
+        if (mpctx->demuxer->s_streams[i])
+            cnt = i + 1;
+    if (cnt > mpctx->sub_counts[SUB_SOURCE_DEMUX])
+        mpctx->sub_counts[SUB_SOURCE_DEMUX] = cnt;
+
+    // TODO: possibly adjust global_sub_pos
+
+    // update global size
+    mpctx->global_sub_size = 0;
+    for (i = 0; i < SUB_SOURCES; i++)
+        mpctx->global_sub_size = mpctx->sub_counts[i];
+}
+
+static int sub_pos_by_source(MPContext *mpctx, int src)
+{
+    int i, cnt = 0;
+    if (src >= SUB_SOURCES || mpctx->sub_counts[src] == 0)
+        return -1;
+    for (i = 0; i < src; i++)
+        cnt += mpctx->sub_counts[i];
+    return cnt;
+}
+
+static int sub_source_and_index_by_pos(MPContext *mpctx, int *pos)
+{
+    int start = 0;
     int i;
     for (i = 0; i < SUB_SOURCES; i++) {
-        int j = mpctx->global_sub_indices[i];
-        if ((j >= 0) && (j > top) && (pos >= j)) {
-            source = i;
-            top = j;
+        int cnt = mpctx->sub_counts[i];
+        if (*pos >= start && *pos < start + cnt) {
+            *pos -= start;
+            return i;
         }
+        start += cnt;
     }
-    return source;
+    *pos = -1;
+    return -1;
+}
+
+static int sub_source_by_pos(MPContext *mpctx, int pos)
+{
+    return sub_source_and_index_by_pos(mpctx, &pos);
+}
+
+static int sub_source_pos(MPContext *mpctx)
+{
+    int pos = mpctx->global_sub_pos;
+    sub_source_and_index_by_pos(mpctx, &pos);
+    return pos;
 }
 
 static int sub_source(MPContext *mpctx)
@@ -1323,11 +1366,14 @@
                            MPContext *mpctx)
 {
     demux_stream_t *const d_sub = mpctx->d_sub;
-    const int global_sub_size = mpctx->global_sub_size;
+    int global_sub_size;
     int source = -1, reset_spu = 0;
+    int source_pos = -1;
     double pts = 0;
     char *sub_name;
 
+    update_global_sub_size(mpctx);
+    global_sub_size = mpctx->global_sub_size;
     if (global_sub_size <= 0)
         return M_PROPERTY_UNAVAILABLE;
 
@@ -1433,15 +1479,17 @@
         return M_PROPERTY_NOT_IMPLEMENTED;
     }
 
-    if (mpctx->global_sub_pos >= 0)
+    if (mpctx->global_sub_pos >= 0) {
         source = sub_source(mpctx);
+        source_pos = sub_source_pos(mpctx);
+    }
 
     mp_msg(MSGT_CPLAYER, MSGL_DBG3,
            "subtitles: %d subs, (v@%d s@%d d@%d), @%d, source @%d\n",
            global_sub_size,
-           mpctx->global_sub_indices[SUB_SOURCE_VOBSUB],
-           mpctx->global_sub_indices[SUB_SOURCE_SUBS],
-           mpctx->global_sub_indices[SUB_SOURCE_DEMUX],
+           mpctx->sub_counts[SUB_SOURCE_VOBSUB],
+           mpctx->sub_counts[SUB_SOURCE_SUBS],
+           mpctx->sub_counts[SUB_SOURCE_DEMUX],
            mpctx->global_sub_pos, source);
 
     mpctx->set_of_sub_pos = -1;
@@ -1459,10 +1507,9 @@
 #endif
 
     if (source == SUB_SOURCE_VOBSUB) {
-        vobsub_id = vobsub_get_id_by_index(vo_vobsub, mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_VOBSUB]);
+        vobsub_id = source_pos;
     } else if (source == SUB_SOURCE_SUBS) {
-        mpctx->set_of_sub_pos =
-            mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_SUBS];
+        mpctx->set_of_sub_pos = source_pos;
 #ifdef CONFIG_ASS
         if (ass_enabled && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos])
             ass_track = mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos];
@@ -1473,8 +1520,7 @@
             vo_osd_changed(OSDTYPE_SUBTITLE);
         }
     } else if (source == SUB_SOURCE_DEMUX) {
-        dvdsub_id =
-            mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_DEMUX];
+        dvdsub_id = source_pos;
         if (d_sub && dvdsub_id < MAX_S_STREAMS) {
             int i = 0;
             // default: assume 1:1 mapping of sid and stream id
@@ -1526,6 +1572,7 @@
                                   MPContext *mpctx)
 {
     int source;
+    update_global_sub_size(mpctx);
     if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
         return M_PROPERTY_UNAVAILABLE;
 
@@ -1562,9 +1609,10 @@
         if (*(int *) arg < 0)
             mpctx->global_sub_pos = -1;
         else if (*(int *) arg != sub_source(mpctx)) {
-            if (*(int *) arg != sub_source_by_pos(mpctx, mpctx->global_sub_indices[*(int *) arg]))
+            int new_pos = sub_pos_by_source(mpctx, *(int *)arg);
+            if (new_pos == -1)
                 return M_PROPERTY_UNAVAILABLE;
-            mpctx->global_sub_pos = mpctx->global_sub_indices[*(int *) arg];
+            mpctx->global_sub_pos = new_pos;
         }
         break;
     case M_PROPERTY_STEP_UP:
@@ -1581,7 +1629,7 @@
             else if (source < -1)
                 source = SUB_SOURCES - 1;
             if (source == cur_source || source == -1 ||
-                    source == sub_source_by_pos(mpctx, mpctx->global_sub_indices[source]))
+                    mpctx->sub_counts[source])
                 step_all -= step;
         }
         if (source == cur_source)
@@ -1589,7 +1637,7 @@
         if (source == -1)
             mpctx->global_sub_pos = -1;
         else
-            mpctx->global_sub_pos = mpctx->global_sub_indices[source];
+            mpctx->global_sub_pos = sub_pos_by_source(mpctx, source);
         break;
     }
     default:
@@ -1604,6 +1652,7 @@
                                    MPContext *mpctx)
 {
     int source, is_cur_source, offset;
+    update_global_sub_size(mpctx);
     if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
         return M_PROPERTY_UNAVAILABLE;
 
@@ -1616,8 +1665,8 @@
     else
         return M_PROPERTY_ERROR;
 
-    offset = mpctx->global_sub_indices[source];
-    if (offset < 0 || source != sub_source_by_pos(mpctx, offset))
+    offset = sub_pos_by_source(mpctx, source);
+    if (offset < 0)
         return M_PROPERTY_UNAVAILABLE;
 
     is_cur_source = sub_source(mpctx) == source;
@@ -1626,7 +1675,7 @@
         if (!arg)
             return M_PROPERTY_ERROR;
         if (is_cur_source) {
-            *(int *) arg = mpctx->global_sub_pos - offset;
+            *(int *) arg = sub_source_pos(mpctx);
             if (source == SUB_SOURCE_VOBSUB)
                 *(int *) arg = vobsub_get_id_by_index(vo_vobsub, *(int *) arg);
         }
@@ -1650,8 +1699,7 @@
             if (source == SUB_SOURCE_VOBSUB)
                 index = vobsub_get_index_by_id(vo_vobsub, index);
             mpctx->global_sub_pos = offset + index;
-            if (index < 0 || mpctx->global_sub_pos >= mpctx->global_sub_size
-                    || sub_source(mpctx) != source) {
+            if (index < 0 || index > mpctx->sub_counts[source]) {
                 mpctx->global_sub_pos = -1;
                 *(int *) arg = -1;
             }
@@ -2385,7 +2433,7 @@
     mpctx->global_sub_size -= count;
     mpctx->set_of_sub_size -= count;
     if (mpctx->set_of_sub_size <= 0)
-        mpctx->global_sub_indices[SUB_SOURCE_SUBS] = -1;
+        mpctx->sub_counts[SUB_SOURCE_SUBS] = 0;
 
     memmove(subs + start, subs + end, after * sizeof(*subs));
     memset(subs + start + after, 0, count * sizeof(*subs));
@@ -2980,9 +3028,7 @@
                 int n = mpctx->set_of_sub_size;
                 add_subtitles(cmd->args[0].v.s, sh_video->fps, 0);
                 if (n != mpctx->set_of_sub_size) {
-                    if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] < 0)
-                        mpctx->global_sub_indices[SUB_SOURCE_SUBS] =
-                            mpctx->global_sub_size;
+                    mpctx->sub_counts[SUB_SOURCE_SUBS]++;
                     ++mpctx->global_sub_size;
                 }
             }
--- a/mp_core.h	Sat Jul 10 18:53:08 2010 +0000
+++ b/mp_core.h	Sat Jul 10 20:48:50 2010 +0000
@@ -110,7 +110,7 @@
     int global_sub_pos; // this encompasses all subtitle sources
     int set_of_sub_pos;
     int set_of_sub_size;
-    int global_sub_indices[SUB_SOURCES];
+    int sub_counts[SUB_SOURCES];
 #ifdef CONFIG_ASS
     // set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i]
     // parsed by libass or NULL if format unsupported
--- a/mplayer.c	Sat Jul 10 18:53:08 2010 +0000
+++ b/mplayer.c	Sat Jul 10 20:48:50 2010 +0000
@@ -1875,32 +1875,42 @@
     return time_frame;
 }
 
-static void select_subtitle(MPContext *mpctx)
+static int select_subtitle(MPContext *mpctx)
 {
   // find the best sub to use
-  int vobsub_index_id = vobsub_get_index_by_id(vo_vobsub, vobsub_id);
+  int id;
+  int found = 0;
   mpctx->global_sub_pos = -1; // no subs by default
-  if (vobsub_index_id >= 0) {
+  if (vobsub_id >= 0) {
     // if user asks for a vobsub id, use that first.
-    mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] + vobsub_index_id;
-  } else if (dvdsub_id >= 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) {
+    id = vobsub_id;
+    found = mp_property_do("sub_vob", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
+  }
+
+  if (!found && dvdsub_id >= 0) {
     // if user asks for a dvd sub id, use that next.
-    mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id;
-  } else if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] >= 0) {
+    id = dvdsub_id;
+    found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
+  }
+
+  if (!found) {
     // if there are text subs to use, use those.  (autosubs come last here)
-    mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_SUBS];
-  } else if (dvdsub_id == -1 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) {
+    id = 0;
+    found = mp_property_do("sub_file", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
+  }
+
+  if (!found && dvdsub_id == -1) {
     // finally select subs by language and container hints
     if (dvdsub_id == -1 && dvdsub_lang)
       dvdsub_id = demuxer_sub_track_by_lang(mpctx->demuxer, dvdsub_lang);
     if (dvdsub_id == -1)
       dvdsub_id = demuxer_default_sub_track(mpctx->demuxer);
-    if (dvdsub_id >= 0)
-      mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id;
+    if (dvdsub_id >= 0) {
+      id = dvdsub_id;
+      found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
+    }
   }
-  // rather than duplicate code, use the SUB_SELECT handler to init the right one.
-  mpctx->global_sub_pos--;
-  mp_property_do("sub",M_PROPERTY_STEP_UP,NULL, mpctx);
+  return found;
 }
 
 #ifdef CONFIG_DVDNAV
@@ -1959,7 +1969,7 @@
     }
 
     audio_delay = 0.0f;
-    mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + mp_dvdnav_number_of_subs(mpctx->stream);
+    mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream);
     if (dvdsub_lang && dvdsub_id == dvdsub_lang_id) {
         dvdsub_lang_id = mp_dvdnav_sid_from_lang(ctx->stream, dvdsub_lang);
         if (dvdsub_lang_id != dvdsub_id) {
@@ -3050,7 +3060,7 @@
 
   // init global sub numbers
   mpctx->global_sub_size = 0;
-  { int i; for (i = 0; i < SUB_SOURCES; i++) mpctx->global_sub_indices[i] = -1; }
+  memset(mpctx->sub_counts, 0, sizeof(mpctx->sub_counts));
 
   if (filename) {
     load_per_protocol_config (mconfig, filename);
@@ -3237,8 +3247,7 @@
       mp_property_do("sub_forced_only", M_PROPERTY_SET, &forced_subs_only, mpctx);
 
       // setup global sub numbering
-      mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] = mpctx->global_sub_size; // the global # of the first vobsub.
-      mpctx->global_sub_size += vobsub_get_indexes_count(vo_vobsub);
+      mpctx->sub_counts[SUB_SOURCE_VOBSUB] = vobsub_get_indexes_count(vo_vobsub);
     }
 
 //============ Open & Sync STREAM --- fork cache2 ====================
@@ -3325,8 +3334,7 @@
   if(audio_id==-1) audio_id=dvd_aid_from_lang(mpctx->stream,audio_lang);
   if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(mpctx->stream,dvdsub_lang);
   // setup global sub numbering
-  mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub.
-  mpctx->global_sub_size += dvd_number_of_subs(mpctx->stream);
+  mpctx->sub_counts[SUB_SOURCE_DEMUX] = dvd_number_of_subs(mpctx->stream);
   current_module=NULL;
 }
 #endif
@@ -3339,8 +3347,7 @@
   if(dvdsub_lang && dvdsub_id==-1)
     dvdsub_lang_id=dvdsub_id=mp_dvdnav_sid_from_lang(mpctx->stream,dvdsub_lang);
   // setup global sub numbering
-  mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub.
-  mpctx->global_sub_size += mp_dvdnav_number_of_subs(mpctx->stream);
+  mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream);
   current_module=NULL;
 }
 #endif
@@ -3433,20 +3440,6 @@
 
 initialized_flags|=INITIALIZED_DEMUXER;
 
-if (mpctx->stream->type != STREAMTYPE_DVD && mpctx->stream->type != STREAMTYPE_DVDNAV) {
-  int i;
-  int maxid = -1;
-  // setup global sub numbering
-  mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub.
-  for (i = 0; i < MAX_S_STREAMS; i++)
-    if (mpctx->demuxer->s_streams[i])
-      maxid = FFMAX(maxid, ((sh_sub_t *)mpctx->demuxer->s_streams[i])->sid);
-  mpctx->global_sub_size += maxid + 1;
-}
-// Make dvdsub_id always selectable if set.
-if (mpctx->global_sub_size <= mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id)
-  mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id + 1;
-
 #ifdef CONFIG_ASS
 if (ass_enabled && ass_library) {
   for (i = 0; i < mpctx->demuxer->num_attachments; ++i) {
@@ -3596,15 +3589,11 @@
     }
     free(tmp);
   }
-  if (mpctx->set_of_sub_size > 0)  {
-      // setup global sub numbering
-      mpctx->global_sub_indices[SUB_SOURCE_SUBS] = mpctx->global_sub_size; // the global # of the first sub.
-      mpctx->global_sub_size += mpctx->set_of_sub_size;
-  }
+  if (mpctx->set_of_sub_size > 0)
+      mpctx->sub_counts[SUB_SOURCE_SUBS] = mpctx->set_of_sub_size;
 }
 
-if (mpctx->global_sub_size) {
-  select_subtitle(mpctx);
+if (select_subtitle(mpctx)) {
   if(subdata)
     switch (stream_dump_type) {
         case 3: list_sub_file(subdata); break;