changeset 265:99d33725395d src

commit Miguel's approach on the time search function (it needs fixing, because it does not use the time table, but interpolates only cell times; but better than not having the function at all)
author mroi
date Mon, 03 Oct 2005 21:07:14 +0000
parents 8c86b61eb06f
children 21ba13a7b77a
files dvdnav.c dvdnav_internal.h searching.c
diffstat 3 files changed, 89 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/dvdnav.c	Wed Apr 20 16:16:20 2005 +0000
+++ b/dvdnav.c	Mon Oct 03 21:07:14 2005 +0000
@@ -203,7 +203,7 @@
 }
 
 /* converts a dvd_time_t to PTS ticks */
-static int64_t dvdnav_convert_time(dvd_time_t *time) {
+int64_t dvdnav_convert_time(dvd_time_t *time) {
   int64_t result;
   int64_t frames;
   
--- a/dvdnav_internal.h	Wed Apr 20 16:16:20 2005 +0000
+++ b/dvdnav_internal.h	Mon Oct 03 21:07:14 2005 +0000
@@ -183,6 +183,11 @@
   char err_str[MAX_ERR_LEN];
 };
 
+/** HELPER FUNCTIONS **/
+
+/* converts a dvd_time_t to PTS ticks */
+int64_t dvdnav_convert_time(dvd_time_t *time);
+
 /** USEFUL MACROS **/
 
 #ifdef __GNUC__
--- a/searching.c	Wed Apr 20 16:16:20 2005 +0000
+++ b/searching.c	Mon Oct 03 21:07:14 2005 +0000
@@ -34,12 +34,6 @@
 
 /* Searching API calls */
 
-dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
-				   uint64_t time) {
-  /* FIXME: Time search the current PGC based on the xxx table */
-  return DVDNAV_STATUS_OK;
-}
-
 /* Scan the ADMAP for a particular block number. */
 /* Return placed in vobu. */
 /* Returns error status */
@@ -101,6 +95,89 @@
   return DVDNAV_STATUS_ERR;
 }
 
+/* FIXME: right now, this function does not use the time tables but interpolates
+   only the cell times */
+dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
+				   uint64_t time) {
+  
+  uint64_t target = time;
+  uint64_t length = 0;
+  uint32_t first_cell_nr, last_cell_nr, cell_nr;
+  int32_t found;
+  cell_playback_t *cell;
+  dvd_state_t *state;
+  dvdnav_status_t result;
+
+  if(this->position_current.still != 0) {
+    printerr("Cannot seek in a still frame.");
+    return DVDNAV_STATUS_ERR;
+  }
+  
+  pthread_mutex_lock(&this->vm_lock);
+  state = &(this->vm->state);
+  if(!state->pgc) {
+    printerr("No current PGC.");
+    pthread_mutex_unlock(&this->vm_lock);
+    return DVDNAV_STATUS_ERR;
+  }
+
+  
+  if (this->pgc_based) {
+    first_cell_nr = 1;
+    last_cell_nr = state->pgc->nr_of_cells;
+  } else {
+    /* Find start cell of program. */
+    first_cell_nr = state->pgc->program_map[state->pgN-1];
+    /* Find end cell of program */
+    if(state->pgN < state->pgc->nr_of_programs)
+      last_cell_nr = state->pgc->program_map[state->pgN] - 1;
+    else
+      last_cell_nr = state->pgc->nr_of_cells;
+  }
+
+  found = 0;
+  for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) {
+    cell =  &(state->pgc->cell_playback[cell_nr-1]);
+    length = dvdnav_convert_time(&cell->playback_time);
+    if (target >= length) {
+      target -= length;
+    } else {
+      /* FIXME: there must be a better way than interpolation */
+      target = target * (cell->last_sector - cell->first_sector + 1) / length;
+      target += cell->first_sector;
+      
+      found = 1;
+      break;
+    }
+  }
+
+  if(found) {
+    int32_t vobu;
+#ifdef LOG_DEBUG
+    fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n",
+	    cell_nr, first_cell_nr, last_cell_nr);
+#endif
+    if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) {
+      int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector;
+      
+      if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) {
+#ifdef LOG_DEBUG
+        fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
+          state->cellN, state->blockN, target, vobu, start);
+#endif
+        this->vm->hop_channel += HOP_SEEK;
+        pthread_mutex_unlock(&this->vm_lock);
+        return DVDNAV_STATUS_OK;
+      }
+    }
+  }
+  
+  fprintf(MSG_OUT, "libdvdnav: Error when seeking\n");
+  printerr("Error when seeking.");
+  pthread_mutex_unlock(&this->vm_lock);
+  return DVDNAV_STATUS_ERR;
+}
+
 dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
 				     uint64_t offset, int32_t origin) {
   uint32_t target = 0;