Index: ext/dvdread/dvdreadsrc.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-ugly/ext/dvdread/dvdreadsrc.c,v
retrieving revision 1.48
diff -u -r1.48 dvdreadsrc.c
--- ext/dvdread/dvdreadsrc.c	19 Oct 2006 10:17:14 -0000	1.48
+++ ext/dvdread/dvdreadsrc.c	11 Nov 2006 22:06:08 -0000
@@ -359,19 +359,9 @@
       src->start_cell, src->last_cell);
 
   /* retrieve position */
-  src->cur_pack = 0;
-  for (i = 0; i < chapter; i++) {
-    gint c1, c2;
-
-    cur_title_get_chapter_bounds (src, i, &c1, &c2);
-
-    while (c1 < c2) {
-      src->cur_pack +=
-          src->cur_pgc->cell_playback[c1].last_sector -
-          src->cur_pgc->cell_playback[c1].first_sector;
-      ++c1;
-    }
-  }
+  guint8 c1, c2;
+  cur_title_get_chapter_bounds (src, chapter, &c1, &c2);
+  src->cur_pack = src->cur_pgc->cell_playback[c1].first_sector;
 
   /* prepare reading for new cell */
   src->new_cell = TRUE;
@@ -676,36 +666,62 @@
   return GST_CLOCK_TIME_NONE;
 }
 
-/* returns the sector in the index at (or before) the given time, or -1 */
+
+/* Returns sector for time <= ts. Sector relative to title_set, not title. */
 static gint
 gst_dvd_read_src_get_sector_from_time (GstDvdReadSrc * src, GstClockTime ts)
 {
-  gint sector, i, j;
+  /* src->vts_tmapt->tmap[] contains the tmaps for all titles in the current
+  title_set, not just the current title.  tmap.map_ent[] contains the sector
+  corresponding to each time at fixed intervals of tmap.tmu seconds. The
+  first entry is for tmap.tmu seconds, not 0 seconds.  To better understand
+  the vts_tmapt, look at the libdvdread function ifoPrint_VTS_TMAPT() in 
+  ifo.print.c */
 
-  if (src->vts_tmapt == NULL || src->vts_tmapt->nr_of_tmaps == 0)
-    return -1;
-
-  sector = 0;
-  for (i = 0; i < src->vts_tmapt->nr_of_tmaps; ++i) {
-    for (j = 0; j < src->vts_tmapt->tmap[i].nr_of_entries; ++j) {
-      GstClockTime entry_time;
+  guint16 i, j;
+  vts_tmap_t tmap;
 
-      entry_time = src->vts_tmapt->tmap[i].tmu * (j + 1) * GST_SECOND;
-      if (entry_time <= ts) {
-        sector = src->vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff;
-      }
-      if (entry_time >= ts) {
-        return sector;
-      }
-    }
+  if (src->vts_tmapt == NULL) 
+  {
+    GST_WARNING_OBJECT (src, 
+      "Trying to get sector from time, but src->vts_tmapt == NULL");
+    return -1;
+  }
+    
+  /* FIXME: I still need someone to veriy that 
+  (tt_srpt->title[title].vts_ttn - 1) always gives the index for the correct
+  tmap. */
+  
+  /* Assigned elsewhere: src->ttn = tt_srpt->title[title].vts_ttn */
+            
+  i = src->ttn -1;       
+  if (i < 0 || i >= src->vts_tmapt->nr_of_tmaps)
+  {
+    GST_ERROR_OBJECT (src, "Trying to used tmap[%d], but nr_of_tmaps = %d", 
+      i, src->vts_tmapt->nr_of_tmaps);
+    return -1;
   }
 
-  if (ts == 0)
-    return 0;
+  tmap = src->vts_tmapt->tmap[i];
+  j = ts / GST_SECOND / tmap.tmu - 1;
+  
+  if (j < 0)
+  {
+    /* FIXME: we should actually return the start sector for the title,
+    which is not in tmap.map_ent[] */
+    j = 0;
+  }
+  else if (j >= tmap.nr_of_entries)
+  {
+    GST_WARNING_OBJECT (src, 
+      "Trying to seek beyond end of title");
+    j = tmap.nr_of_entries - 1;
+  }
 
-  return -1;
+  return tmap.map_ent[j] & 0x7fffffff; // Some high bits aren't used.
 }
 
+
 typedef enum
 {
   GST_DVD_READ_OK = 0,
@@ -1501,54 +1517,56 @@
   return res;
 }
 
+
+/* sector is absolute (i.e., relative to title_set, not title) */
 static gboolean
 gst_dvd_read_src_goto_sector (GstDvdReadSrc * src, int angle)
 {
-  gint seek_to = src->cur_pack;
-  gint chapter, sectors, next, cur, i;
+  guint32 seek_to = src->cur_pack;
+  guint16 chap, cell;
+
+  /* find chapter and cell containing sector src->cur_pack */
+  for (chap = 0; chap < src->num_chapters; chap++)
+  {
+    guint8 c1, c2;
+    cur_title_get_chapter_bounds (src, chap, &c1, &c2);
 
-  /* retrieve position */
-  src->cur_pack = 0;
-  for (i = 0; i < src->num_chapters; i++) {
-    gint c1, c2;
-
-    cur_title_get_chapter_bounds (src, i, &c1, &c2);
-
-    for (next = cur = c1; cur < c2;) {
-      if (next != cur) {
-        sectors =
-            src->cur_pgc->cell_playback[cur].last_sector -
-            src->cur_pgc->cell_playback[cur].first_sector;
-        if (src->cur_pack + sectors > seek_to) {
-          chapter = i;
+    for (cell = c1; cell < c2;) {
+      if (seek_to < src->cur_pgc->cell_playback[cell].first_sector)
+      {
+        /* HACK: Some initial seek to FORMAT_BYTES 0 is being called, maybe
+        from GstBaseSrc, which is breaking things for a title_set with more
+        than one title.  As an aside, querying and seeking by sector (or
+        bytes, which are converted to sectors) is totally broken because of
+        further title starts at sector 0 assumptions throughout the code */
+        seek_to = src->cur_pgc->cell_playback[cell].first_sector;
+        goto done;
+      }
+      if (src->cur_pgc->cell_playback[cell].first_sector <= src->cur_pack &&
+          src->cur_pgc->cell_playback[cell].last_sector >= src->cur_pack)
+      {
+          /* seek_to is in the sector interval for this chap and cell */
           goto done;
-        }
-        src->cur_pack += sectors;
       }
-      cur = next;
-      if (src->cur_pgc->cell_playback[cur].block_type == BLOCK_TYPE_ANGLE_BLOCK)
-        cur += angle;
-      next = gst_dvd_read_src_get_next_cell (src, src->cur_pgc, cur);
+      if (src->cur_pgc->cell_playback[cell].block_type == BLOCK_TYPE_ANGLE_BLOCK)
+        cell += angle;
+      cell = gst_dvd_read_src_get_next_cell (src, src->cur_pgc, cell);
     }
   }
 
-  GST_DEBUG_OBJECT (src, "Seek to sector %u failed", seek_to);
+  GST_WARNING_OBJECT (src, "Seek to sector %u failed", seek_to);
 
   return FALSE;
 
 done:
   {
-    /* so chapter $chapter and cell $cur contain our sector
-     * of interest. Let's go there! */
     GST_INFO_OBJECT (src, "Seek succeeded, going to chapter %u, cell %u",
-        chapter + 1, cur);
-
-    gst_dvd_read_src_goto_chapter (src, chapter);
-    src->cur_cell = cur;
-    src->next_cell = next;
+        chap + 1, cell);
+    gst_dvd_read_src_goto_chapter (src, chap);
+    src->cur_cell = cell;
+    src->next_cell = gst_dvd_read_src_get_next_cell (src, src->cur_pgc, cell);
     src->new_cell = FALSE;
     src->cur_pack = seek_to;
-
     return TRUE;
   }
 }
