[DVDnav-discuss] r928 - trunk/libdvdnav2/src/searching.c

nicodvb subversion at mplayerhq.hu
Sun Apr 29 22:15:39 CEST 2007


Author: nicodvb
Date: Sun Apr 29 22:15:38 2007
New Revision: 928

Log:
ported actual implementation of dvdnav_time_search() from libdvdnav

Modified:
   trunk/libdvdnav2/src/searching.c

Modified: trunk/libdvdnav2/src/searching.c
==============================================================================
--- trunk/libdvdnav2/src/searching.c	(original)
+++ trunk/libdvdnav2/src/searching.c	Sun Apr 29 22:15:38 2007
@@ -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,87 @@ static dvdnav_status_t dvdnav_scan_admap
   return DVDNAV_STATUS_ERR;
 }
 
+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;
+
+  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;
+  }
+
+  
+  this->cur_cell_time = 0;  
+  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]);
+    if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL)
+      continue;
+    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) {
+    uint32_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) {
+      uint32_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;



More information about the DVDnav-discuss mailing list