resindvd: Map audio and subpicture logical streams to physical.
authorJan Schmidt <thaytan@noraisin.net>
Fri, 24 Apr 2009 13:07:30 +0000 (14:07 +0100)
committerJan Schmidt <thaytan@noraisin.net>
Wed, 29 Apr 2009 20:02:15 +0000 (21:02 +0100)
The logical audio and subpicture stream number doesn't always correspond
with the physical substream it is coming from. When configuring the demuxer
pads, use the mapping table provided in each PGC to get the layout and
ensure the demuxer creates the correct pads.

ext/resindvd/gstmpegdemux.c
ext/resindvd/resindvdsrc.c

index bee7f43ffcf159b4c98c01cccd68edf737700481..cc37ec4eabb65d49aaab9a01e3481d9c1bf91aa5 100644 (file)
@@ -622,11 +622,17 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
       if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
         continue;
 
+      g_snprintf (cur_stream_name, 32, "audio-%d-stream", i);
+      if (!gst_structure_get_int (structure, cur_stream_name, &stream_id))
+        continue;
+      if (stream_id < 0 || stream_id >= MAX_DVD_AUDIO_STREAMS)
+        continue;
+
       demux->audio_stream_types[i] = stream_format;
       switch (stream_format) {
         case 0x0:
           /* AC3 */
-          stream_id = 0x80 + i;
+          stream_id += 0x80;
           GST_DEBUG_OBJECT (demux,
               "Audio stream %d format %d ID 0x%02x - AC3", i,
               stream_format, stream_id);
@@ -636,7 +642,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
         case 0x3:
           /* MPEG audio without and with extension stream are 
            * treated the same */
-          stream_id = 0xC0 + i;
+          stream_id += 0xC0;
           GST_DEBUG_OBJECT (demux,
               "Audio stream %d format %d ID 0x%02x - MPEG audio", i,
               stream_format, stream_id);
@@ -644,7 +650,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
           break;
         case 0x4:
           /* LPCM */
-          stream_id = 0xA0 + i;
+          stream_id += 0xA0;
           GST_DEBUG_OBJECT (demux,
               "Audio stream %d format %d ID 0x%02x - DVD LPCM", i,
               stream_format, stream_id);
@@ -653,7 +659,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
           break;
         case 0x6:
           /* DTS */
-          stream_id = 0x88 + i;
+          stream_id += 0x88;
           GST_DEBUG_OBJECT (demux,
               "Audio stream %d format %d ID 0x%02x - DTS", i,
               stream_format, stream_id);
@@ -673,16 +679,23 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
     /* And subtitle streams */
     for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) {
       gint stream_format;
+      gint stream_id;
 
       g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i);
-
       if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
         continue;
 
+      g_snprintf (cur_stream_name, 32, "subpicture-%d-stream", i);
+      if (!gst_structure_get_int (structure, cur_stream_name, &stream_id))
+        continue;
+      if (stream_id < 0 || stream_id >= MAX_DVD_SUBPICTURE_STREAMS)
+        continue;
+
       GST_DEBUG_OBJECT (demux, "Subpicture stream %d ID 0x%02x", i, 0x20 + i);
 
       /* Retrieve the subpicture stream to force pad creation */
-      temp = gst_flups_demux_get_stream (demux, 0x20 + i, ST_PS_DVD_SUBPICTURE);
+      temp = gst_flups_demux_get_stream (demux, 0x20 + stream_id,
+          ST_PS_DVD_SUBPICTURE);
     }
 
     GST_DEBUG_OBJECT (demux, "Created all pads from Language Codes event, "
index d2e3b25a77e1c78f181b18426ab17378410e8cd0..2ad1125605d1851111b315c379cc21073fbcb0b3 100644 (file)
@@ -685,8 +685,8 @@ get_current_pgc (resinDvdSrc * src)
       DVDNAV_STATUS_OK)
     return NULL;
 
-  /* To find the right tmap, we need the title number within this VTS (vts_ttn)
-   *    * from the VMG tt_srpt table... */
+  /* To find the right PGC, we need the title number within this VTS (vts_ttn)
+   * from the VMG tt_srpt table... */
   if (title < 1 || title > src->vmg_file->tt_srpt->nr_of_srpts)
     return NULL;
 
@@ -864,6 +864,9 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
           "CELL change dur now %" GST_TIME_FORMAT " position now %"
           GST_TIME_FORMAT, GST_TIME_ARGS (src->pgc_duration),
           GST_TIME_ARGS (src->cur_position));
+
+      rsn_dvdsrc_prepare_streamsinfo_event (src);
+
       break;
     }
     case DVDNAV_SPU_CLUT_CHANGE:
@@ -885,9 +888,6 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
 
       src->in_menu = !dvdnav_is_domain_vts (src->dvdnav);
 
-      if (!dvdnav_is_domain_fp (src->dvdnav))
-        rsn_dvdsrc_prepare_streamsinfo_event (src);
-
       break;
     }
     case DVDNAV_AUDIO_STREAM_CHANGE:{
@@ -1018,7 +1018,7 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf)
   /* Push in-band events now that we've dropped the dvd_lock, before
    * we change segment */
   if (streams_event) {
-    GST_LOG_OBJECT (src, "Pushing stream event");
+    GST_LOG_OBJECT (src, "Pushing stream layout event");
     gst_pad_push_event (GST_BASE_SRC_PAD (src), streams_event);
   }
   if (clut_event) {
@@ -1475,8 +1475,8 @@ rsn_dvdsrc_prepare_spu_stream_event (resinDvdSrc * src, guint8 logical_stream,
   src->cur_spu_phys_stream = phys_stream;
   src->cur_spu_forced_only = forced_only;
 
-  GST_DEBUG_OBJECT (src, "Preparing SPU change, phys %d forced %d",
-      phys_stream, forced_only);
+  GST_DEBUG_OBJECT (src, "Preparing SPU change, log %d phys %d forced %d",
+      logical_stream, phys_stream, forced_only);
 
   s = gst_structure_new ("application/x-gst-dvd",
       "event", G_TYPE_STRING, "dvd-set-subpicture-track",
@@ -1506,6 +1506,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
   gchar *t;
   gboolean is_widescreen;
   gboolean have_audio;
+  gboolean have_subp;
 
   if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) {
     if (src->vts_attrs)
@@ -1561,6 +1562,16 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
   have_audio = FALSE;
   for (i = 0; i < n_audio; i++) {
     const audio_attr_t *a = a_attrs + i;
+    gint phys_id = dvdnav_get_audio_logical_stream (src->dvdnav, (guint) i);
+
+    if (phys_id == -1) {
+      GST_DEBUG_OBJECT (src, "No substream ID in map for audio %d. Skipping.",
+          i);
+      continue;
+    }
+
+    GST_DEBUG_OBJECT (src, "mapped logical audio %d to MPEG substream %d",
+        i, phys_id);
 
 #if 1
     /* FIXME: Only output A52 streams for now, until the decoder switching
@@ -1573,13 +1584,17 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
 #endif
     have_audio = TRUE;
 
+    GST_DEBUG_OBJECT (src, "Audio stream %d is format %d, substream %d", i,
+        (int) a->audio_format, phys_id);
+
+    t = g_strdup_printf ("audio-%d-stream", i);
+    gst_structure_set (s, t, G_TYPE_INT, phys_id, NULL);
+    g_free (t);
+
     t = g_strdup_printf ("audio-%d-format", i);
     gst_structure_set (s, t, G_TYPE_INT, (int) a->audio_format, NULL);
     g_free (t);
 
-    GST_DEBUG_OBJECT (src, "Audio stream %d is format %d", i,
-        (int) a->audio_format);
-
     if (a->lang_type) {
       t = g_strdup_printf ("audio-%d-language", i);
       lang_code[0] = (a->lang_code >> 8) & 0xff;
@@ -1594,17 +1609,29 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
 
   if (have_audio == FALSE) {
     /* Always create at least one audio stream */
-    gst_structure_set (s, "audio-0-format", G_TYPE_INT, (int) 0, NULL);
+    gst_structure_set (s, "audio-0-format", G_TYPE_INT, (int) 0,
+        "audio-0-stream", G_TYPE_INT, (int) 0, NULL);
   }
 
   /* subpictures */
-  if (n_subp == 0) {
-    /* Always create at least one subpicture stream */
-    gst_structure_set (s, "subpicture-0-format", G_TYPE_INT, (int) 0, NULL);
-    gst_structure_set (s, "subpicture-0-language", G_TYPE_STRING, "MENU", NULL);
-  }
+  have_subp = FALSE;
   for (i = 0; i < n_subp; i++) {
     const subp_attr_t *u = s_attrs + i;
+    gint phys_id = dvdnav_get_spu_logical_stream (src->dvdnav, (guint) i);
+
+    if (phys_id == -1) {
+      GST_DEBUG_OBJECT (src, "No substream ID in map for subpicture %d. "
+          "Skipping", i);
+      continue;
+    }
+    have_subp = TRUE;
+
+    GST_DEBUG_OBJECT (src, "mapped logical subpicture %d to MPEG substream %d",
+        i, phys_id);
+
+    t = g_strdup_printf ("subpicture-%d-stream", i);
+    gst_structure_set (s, t, G_TYPE_INT, (int) phys_id, NULL);
+    g_free (t);
 
     t = g_strdup_printf ("subpicture-%d-format", i);
     gst_structure_set (s, t, G_TYPE_INT, (int) 0, NULL);
@@ -1623,6 +1650,12 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
     GST_DEBUG_OBJECT (src, "Subpicture stream %d is language %s", i,
         lang_code[0] ? lang_code : "NONE");
   }
+  if (!have_subp) {
+    /* Always create at least one subpicture stream */
+    gst_structure_set (s, "subpicture-0-format", G_TYPE_INT, (int) 0,
+        "subpicture-0-language", G_TYPE_STRING, "MENU",
+        "subpicture-0-stream", G_TYPE_INT, (int) 0, NULL);
+  }
 
   if (src->streams_event)
     gst_event_unref (src->streams_event);
@@ -1655,7 +1688,7 @@ rsn_dvdsrc_prepare_clut_change_event (resinDvdSrc * src, const guint32 * clut)
   /* Create the DVD event and put the structure into it. */
   event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, structure);
 
-  GST_LOG_OBJECT (src, "pushing clut change event %" GST_PTR_FORMAT, event);
+  GST_LOG_OBJECT (src, "preparing clut change event %" GST_PTR_FORMAT, event);
 
   if (src->clut_event)
     gst_event_unref (src->clut_event);