diff options
Diffstat (limited to 'lib/libdvd/libdvdnav/src/searching.c')
-rw-r--r-- | lib/libdvd/libdvdnav/src/searching.c | 1426 |
1 files changed, 0 insertions, 1426 deletions
diff --git a/lib/libdvd/libdvdnav/src/searching.c b/lib/libdvd/libdvdnav/src/searching.c deleted file mode 100644 index 3f4a6df1e4..0000000000 --- a/lib/libdvd/libdvdnav/src/searching.c +++ /dev/null @@ -1,1426 +0,0 @@ -/* - * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> - * - * This file is part of libdvdnav, a DVD navigation library. - * - * libdvdnav is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * libdvdnav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with libdvdnav; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <assert.h> -#include <inttypes.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <sys/time.h> -#include "dvdnav/dvdnav.h" -#include <dvdread/nav_types.h> -#include <dvdread/ifo_types.h> -#include "remap.h" -#include "vm/decoder.h" -#include "vm/vm.h" -#include "dvdnav_internal.h" -#include <dvdread/ifo_read.h> - -/* -#define LOG_DEBUG -*/ - -/* Searching API calls */ - -/* Scan the ADMAP for a particular block number. */ -/* Return placed in vobu. */ -/* Returns error status */ -/* FIXME: Maybe need to handle seeking outside current cell. */ -static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, int next, uint32_t *vobu) { - vobu_admap_t *admap = NULL; - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); -#endif - *vobu = -1; - - /* Search through the VOBU_ADMAP for the nearest VOBU - * to the target block */ - switch(domain) { - case FP_DOMAIN: - case VMGM_DOMAIN: - admap = this->vm->vmgi->menu_vobu_admap; - break; - case VTSM_DOMAIN: - admap = this->vm->vtsi->menu_vobu_admap; - break; - case VTS_DOMAIN: - admap = this->vm->vtsi->vts_vobu_admap; - break; - default: - fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); - } - if(admap) { - uint32_t address = 0; - uint32_t vobu_start, next_vobu; - int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE; - - /* Search through ADMAP for best sector */ - vobu_start = SRI_END_OF_CELL; - /* FIXME: Implement a faster search algorithm */ - while(address < admap_entries) { - next_vobu = admap->vobu_start_sectors[address]; - - /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ - - if(vobu_start <= seekto_block && next_vobu > seekto_block) - break; - vobu_start = next_vobu; - address++; - } - *vobu = next ? next_vobu : vobu_start; - return DVDNAV_STATUS_OK; - } - fprintf(MSG_OUT, "libdvdnav: admap not located\n"); - 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; - - 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((state->pgc->prohibited_ops.title_or_time_play == 1) || - (this->pci.pci_gi.vobu_uop_ctl.title_or_time_play == 1 )){ - printerr("operation forbidden."); - 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; - } - - /* FIXME: using time map is not going to work unless we are pgc_based */ - /* we'd need to recalculate the time to be relative to full pgc first*/ - if(!this->pgc_based) - { -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: time_search - not pgc based\n"); -#endif - goto timemapdone; - } - - if(!this->vm->vtsi->vts_tmapt){ - /* no time map for this program chain */ -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: time_search - no time map for this program chain\n"); -#endif - goto timemapdone; - } - - if(this->vm->vtsi->vts_tmapt->nr_of_tmaps < state->pgcN){ - /* to few time maps for this program chain */ -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: time_search - to few time maps for this program chain\n"); -#endif - goto timemapdone; - } - - /* get the tmpat corresponding to the pgc */ - vts_tmap_t *tmap = &(this->vm->vtsi->vts_tmapt->tmap[state->pgcN-1]); - - if(tmap->tmu == 0){ - /* no time unit for this time map */ -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: time_search - no time unit for this time map\n"); -#endif - goto timemapdone; - } - - /* time is in pts (90khz clock), get the number of tmu's that represent */ - /* first entry defines at time tmu not time zero */ - int entry = time / tmap->tmu / 90000 - 1; - if(entry > tmap->nr_of_entries) - entry = tmap->nr_of_entries -1; - - if(entry > 0) - { - /* get the table entry, disregarding marking of discontinuity */ - target = tmap->map_ent[entry] & 0x7fffffff; - } - else - { - /* start from first vobunit */ - target = state->pgc->cell_playback[first_cell_nr-1].first_sector;; - } - - /* if we have an additional entry we can interpolate next position */ - /* allowed only if next entry isn't discontinious */ - - if( entry < tmap->nr_of_entries - 1) - { - const uint32_t target2 = tmap->map_ent[entry+1]; - const uint64_t timeunit = tmap->tmu*90000; - if( !( target2 & 0x80000000) ) - { - length = target2 - target; - target += (uint32_t) (length * ( time - (entry+1)*timeunit ) / timeunit); - } - } - found = 1; - -timemapdone: - - found = 0; - for(cell_nr = first_cell_nr; cell_nr <= last_cell_nr; 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; - - if(found) { - - if (target >= cell->first_sector - && target <= cell->last_sector) - break; - - } else { - - length = dvdnav_convert_time(&cell->playback_time); - if (time >= length) { - time -= length; - } else { - /* FIXME: there must be a better way than interpolation */ - target = time * (cell->last_sector - cell->first_sector + 1) / length; - target += cell->first_sector; - - #ifdef LOG_DEBUG - if( cell->first_sector > target || target > cell->last_sector ) - fprintf(MSG_OUT, "libdvdnav: time_search - sector is not within cell min:%u, max:%u, cur:%u\n", cell->first_sector, cell->last_sector, target); - #endif - - 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, 0, &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; - uint32_t current_pos; - uint32_t cur_sector; - uint32_t cur_cell_nr; - uint32_t length = 0; - uint32_t first_cell_nr, last_cell_nr, cell_nr; - int32_t found; - int forward = 0; - 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; - } - - result = dvdnav_get_position(this, &target, &length); - if(!result) { - printerr("Cannot get current position"); - 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; - } -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: seeking to offset=%llu pos=%u length=%u\n", offset, target, length); - fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); -#endif - - current_pos = target; - cur_sector = this->vobu.vobu_start + this->vobu.blockN; - cur_cell_nr = state->cellN; - - switch(origin) { - case SEEK_SET: - if(offset >= length) { - printerr("Request to seek behind end."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - target = offset; - break; - case SEEK_CUR: - if(target + offset >= length) { - printerr("Request to seek behind end."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - target += offset; - break; - case SEEK_END: - if(length < offset) { - printerr("Request to seek before start."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - target = length - offset; - break; - default: - /* Error occured */ - printerr("Illegal seek mode."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - forward = target > current_pos; - - 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 = cell->last_sector - cell->first_sector + 1; - if (target >= length) { - target -= length; - } else { - /* convert the target sector from Cell-relative to absolute physical sector */ - target += cell->first_sector; - if (forward && (cell_nr == cur_cell_nr)) { - uint32_t vobu; - /* if we are seeking forward from the current position, make sure - * we move to a new position that is after our current position. - * simply truncating to the vobu will go backwards */ - if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) != DVDNAV_STATUS_OK) - break; - if (vobu <= cur_sector) { - if (dvdnav_scan_admap(this, state->domain, target, 1, &vobu) != DVDNAV_STATUS_OK) - break; - if (vobu > cell->last_sector) { - if (cell_nr == last_cell_nr) - break; - cell_nr++; - cell = &(state->pgc->cell_playback[cell_nr-1]); - target = cell->first_sector; - } else { - target = vobu; - } - } - } - 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, 0, &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"); - fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); - printerr("Error when seeking."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; -} - -dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { - int32_t title, old_part; - - if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) - return dvdnav_part_play(this, title, part); - return DVDNAV_STATUS_ERR; -} - -dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { - pthread_mutex_lock(&this->vm_lock); - if(!this->vm->state.pgc) { - printerr("No current PGC."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); -#endif - if (!vm_jump_prev_pg(this->vm)) { - fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); - printerr("Skip to previous chapter failed."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - this->cur_cell_time = 0; - this->position_current.still = 0; - this->vm->hop_channel++; -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); -#endif - pthread_mutex_unlock(&this->vm_lock); - - return DVDNAV_STATUS_OK; -} - -dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { - pthread_mutex_lock(&this->vm_lock); - if(!this->vm->state.pgc) { - printerr("No current PGC."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: top chapter\n"); -#endif - if (!vm_jump_top_pg(this->vm)) { - fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); - printerr("Skip to top chapter failed."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - this->cur_cell_time = 0; - this->position_current.still = 0; - this->vm->hop_channel++; -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); -#endif - pthread_mutex_unlock(&this->vm_lock); - - return DVDNAV_STATUS_OK; -} - -dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) { - vm_t *try_vm; - - pthread_mutex_lock(&this->vm_lock); - if(!this->vm->state.pgc) { - printerr("No current PGC."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: next chapter\n"); -#endif - /* make a copy of current VM and try to navigate the copy to the next PG */ - try_vm = vm_new_copy(this->vm); - if (!vm_jump_next_pg(try_vm) || try_vm->stopped) { - vm_free_copy(try_vm); - /* next_pg failed, try to jump at least to the next cell */ - try_vm = vm_new_copy(this->vm); - vm_get_next_cell(try_vm); - if (try_vm->stopped) { - vm_free_copy(try_vm); - fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n"); - printerr("Skip to next chapter failed."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - } - this->cur_cell_time = 0; - /* merge changes on success */ - vm_merge(this->vm, try_vm); - vm_free_copy(try_vm); - this->position_current.still = 0; - this->vm->hop_channel++; -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); -#endif - pthread_mutex_unlock(&this->vm_lock); - - return DVDNAV_STATUS_OK; -} - -dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { - vm_t *try_vm; - - pthread_mutex_lock(&this->vm_lock); - if(!this->vm->state.pgc) { - printerr("No current PGC."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - - this->cur_cell_time = 0; - /* make a copy of current VM and try to navigate the copy to the menu */ - try_vm = vm_new_copy(this->vm); - if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) { - /* Try resume */ - if (vm_jump_resume(try_vm) && !try_vm->stopped) { - /* merge changes on success */ - vm_merge(this->vm, try_vm); - vm_free_copy(try_vm); - this->position_current.still = 0; - this->vm->hop_channel++; - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_OK; - } - } - if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; - - if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { - /* merge changes on success */ - vm_merge(this->vm, try_vm); - vm_free_copy(try_vm); - this->position_current.still = 0; - this->vm->hop_channel++; - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_OK; - } else { - vm_free_copy(try_vm); - printerr("No such menu or menu not reachable."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } -} - -dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, - uint32_t *len) { - uint32_t cur_sector; - int32_t cell_nr, first_cell_nr, last_cell_nr; - cell_playback_t *cell; - dvd_state_t *state; - - if(!this->started) { - printerr("Virtual DVD machine not started."); - return DVDNAV_STATUS_ERR; - } - - pthread_mutex_lock(&this->vm_lock); - state = &(this->vm->state); - if(!state->pgc || this->vm->stopped) { - printerr("No current PGC."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - if (this->position_current.hop_channel != this->vm->hop_channel || - this->position_current.domain != state->domain || - this->position_current.vts != state->vtsN || - this->position_current.cell_restart != state->cell_restart) { - printerr("New position not yet determined."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - - /* Get current sector */ - cur_sector = this->vobu.vobu_start + this->vobu.blockN; - - 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; - } - - *pos = -1; - *len = 0; - for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) { - cell = &(state->pgc->cell_playback[cell_nr-1]); - if (cell_nr == state->cellN) { - /* the current sector is in this cell, - * pos is length of PG up to here + sector's offset in this cell */ - *pos = *len + cur_sector - cell->first_sector; - } - *len += cell->last_sector - cell->first_sector + 1; - } - - assert((signed)*pos != -1); - - pthread_mutex_unlock(&this->vm_lock); - - return DVDNAV_STATUS_OK; -} - -dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, - uint32_t *pos, - uint32_t *len) { - uint32_t cur_sector; - uint32_t first_cell_nr; - uint32_t last_cell_nr; - cell_playback_t *first_cell; - cell_playback_t *last_cell; - dvd_state_t *state; - - state = &(this->vm->state); - if(!state->pgc) { - printerr("No current PGC."); - return DVDNAV_STATUS_ERR; - } - - /* Get current sector */ - cur_sector = this->vobu.vobu_start + this->vobu.blockN; - - /* Now find first and last cells in title. */ - first_cell_nr = state->pgc->program_map[0]; - first_cell = &(state->pgc->cell_playback[first_cell_nr-1]); - last_cell_nr = state->pgc->nr_of_cells; - last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); - - *pos = cur_sector - first_cell->first_sector; - *len = last_cell->last_sector - first_cell->first_sector; - - return DVDNAV_STATUS_OK; -} - -uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times, uint64_t *duration) { - int32_t retval=0; - uint16_t parts, i; - title_info_t *ptitle = NULL; - ptt_info_t *ptt = NULL; - ifo_handle_t *ifo = NULL; - pgc_t *pgc; - cell_playback_t *cell; - uint64_t length, *tmp=NULL; - - *times = NULL; - *duration = 0; - pthread_mutex_lock(&this->vm_lock); - if(!this->vm->vmgi) { - printerr("Bad VM state or missing VTSI."); - goto fail; - } - if(!this->started) { - /* don't report an error but be nice */ - vm_start(this->vm); - this->started = 1; - } - ifo = vm_get_title_ifo(this->vm, title); - if(!ifo || !ifo->vts_pgcit) { - printerr("Couldn't open IFO for chosen title, exit."); - retval = 0; - goto fail; - } - - ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; - parts = ptitle->nr_of_ptts; - ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; - - tmp = calloc(1, sizeof(uint64_t)*parts); - if(!tmp) - goto fail; - - length = 0; - for(i=0; i<parts; i++) { - uint32_t cellnr, endcellnr; - if (ptt[i].pgcn == 0 || ptt[i].pgcn > ifo->vts_pgcit->nr_of_pgci_srp) { - printerr("PGCN out of bounds."); - continue; - } - if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >= ifo->vts_pgcit->last_byte) { - printerr("PGC start out of bounds"); - continue; - } - pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; - if (pgc == NULL) { - printerr("PGC missing."); - continue; - } - if (pgc->program_map == NULL) { - printerr("Program map missing."); - continue; - } - if(ptt[i].pgn == 0 || ptt[i].pgn > pgc->nr_of_programs) { - printerr("WRONG part number."); - goto fail; - } - - if (pgc->nr_of_cells == 0) { - printerr("Number of cells cannot be 0"); - continue; - } - if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) { - printerr("Cell new row cannot be 0"); - continue; - } - if (pgc->cell_playback == NULL) { - printerr("Cell missing"); - continue; - } - - if(ptt[i].pgn < pgc->nr_of_programs) - endcellnr = pgc->program_map[ptt[i].pgn]; - else - endcellnr = 0; - - do { - cell = &pgc->cell_playback[cellnr-1]; - if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && - cell->block_mode != BLOCK_MODE_FIRST_CELL - )) - { - tmp[i] = length + dvdnav_convert_time(&cell->playback_time); - length = tmp[i]; - } - cellnr++; - } while(cellnr < endcellnr); - } - *duration = length; - vm_ifo_close(ifo); - ifo = NULL; - retval = parts; - *times = tmp; - -fail: - pthread_mutex_unlock(&this->vm_lock); - if(!retval && ifo) - vm_ifo_close(ifo); - if(!retval && tmp) - free(tmp); - return retval; -} - -dvdnav_status_t dvdnav_get_state(dvdnav_t *this, dvd_state_t *save_state) -{ - if(!this || !this->vm) return DVDNAV_STATUS_ERR; - - pthread_mutex_lock(&this->vm_lock); - - if( !vm_get_state(this->vm, save_state) ) - { - printerr("Failed to get vm state."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_OK; -} - -dvdnav_status_t dvdnav_set_state(dvdnav_t *this, dvd_state_t *save_state) -{ - if(!this || !this->vm) - { - printerr("Passed a NULL pointer."); - return DVDNAV_STATUS_ERR; - } - - if(!this->started) { - printerr("Virtual DVD machine not started."); - return DVDNAV_STATUS_ERR; - } - - pthread_mutex_lock(&this->vm_lock); - - /* reset the dvdnav state */ - memset(&this->pci,0,sizeof(this->pci)); - memset(&this->dsi,0,sizeof(this->dsi)); - this->last_cmd_nav_lbn = SRI_END_OF_CELL; - - /* Set initial values of flags */ - this->position_current.still = 0; - this->skip_still = 0; - this->sync_wait = 0; - this->sync_wait_skip = 0; - this->spu_clut_changed = 0; - - - /* set the state. this will also start the vm on that state */ - /* means the next read block should be comming from that new */ - /* state */ - if( !vm_set_state(this->vm, save_state) ) - { - printerr("Failed to set vm state."); - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_ERR; - } - - pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_OK; -} - - - -/* Get an admap and admap_len */ -static vobu_admap_t* dvdnav_admap_get(dvdnav_t *this, dvd_state_t *state, - int32_t *admap_len) { - vobu_admap_t *admap = NULL; - switch(state->domain) { - case FP_DOMAIN: - case VMGM_DOMAIN: - admap = this->vm->vmgi->menu_vobu_admap; - break; - case VTSM_DOMAIN: - admap = this->vm->vtsi->menu_vobu_admap; - break; - case VTS_DOMAIN: - admap = this->vm->vtsi->vts_vobu_admap; - break; - default: { - fprintf(MSG_OUT, "Unknown domain"); - return NULL; - } - } - if (admap == NULL) return NULL; - - *admap_len = (admap->last_byte + 1 - VOBU_ADMAP_SIZE) / VOBU_ADMAP_SIZE; - if (*admap_len <= 0) { - fprintf(MSG_OUT, "admap_len <= 0"); - return NULL; - } - return admap; -} - -/* Get a tmap, tmap_len and tmap_interval */ -static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state, - int32_t *tmap_len, int32_t *tmap_interval) { - int32_t vts_idx = 0; - domain_t domain; - ifo_handle_t *ifo = NULL; - vts_tmapt_t *tmapt = NULL; - uint16_t tmap_count = 0; - int32_t pgcN = 0; - vts_tmap_t *tmap = NULL; - int32_t result = 0; - - vts_idx = state->vtsN; - domain = state->domain; - switch(domain) { - case FP_DOMAIN: - case VTSM_DOMAIN: - case VMGM_DOMAIN: { - ifo = this->vm->vmgi; - break; - } - case VTS_DOMAIN: { - ifo = this->vm->vtsi; - break; - } - default: { - fprintf(MSG_OUT, "unknown domain for tmap"); - return NULL; - } - } - if (ifo == NULL) return NULL; - tmapt = ifo->vts_tmapt; - /* HACK: ifo->vts_tmapt is NULL b/c ifo_read.c never loads it - * load ifo->vts_tmapt directly*/ - if (tmapt == NULL) { - result = ifoRead_VTS_TMAPT(ifo); - if (!result) { - return NULL; - } - tmapt = ifo->vts_tmapt; - if (tmapt == NULL) return NULL; - } - - tmap_count = tmapt->nr_of_tmaps; - pgcN = state->pgcN - 1; /* -1 b/c pgcN is base1 */ - if (pgcN < 0) { - fprintf(MSG_OUT, "pgcN < 0"); - return NULL; - } - - /* get tmap */ - switch(domain) { - case FP_DOMAIN: - case VMGM_DOMAIN: - case VTSM_DOMAIN: { - if (tmap_count == 0) { - fprintf(MSG_OUT, "tmap_count == 0"); - return NULL; - } - tmap = &tmapt->tmap[0]; /* ASSUME: vmgi only has one time map */ - break; - } - case VTS_DOMAIN: { - if (pgcN >= tmap_count) { - fprintf(MSG_OUT, "pgcN >= tmap_count; pgcN=%i tmap_count=%i", - pgcN, tmap_count); - return NULL; - } - tmap = &tmapt->tmap[pgcN]; - break; - } - } - if (tmap == NULL) return NULL; - - /* tmap->tmu is in seconds; convert to millisecs */ - *tmap_interval = tmap->tmu * 1000; - if (*tmap_interval == 0) { - fprintf(MSG_OUT, "tmap_interval == 0"); - return NULL; - } - *tmap_len = tmap->nr_of_entries; - if (*tmap_len == 0) { - fprintf(MSG_OUT, "tmap_len == 0"); - return NULL; - } - return tmap; -} - -/* Get a sector from a tmap */ -static int32_t dvdnav_tmap_get_entry(vts_tmap_t *tmap, uint16_t tmap_len, - int32_t idx, uint32_t *sector) { - /* tmaps start at idx 0 which represents a sector at time 1 * tmap_interval - * this creates a "fake" tmap index at idx -1 for sector 0 */ - if (idx == TMAP_IDX_EDGE_BGN) { - *sector = 0; - return 1; - } - if (idx < TMAP_IDX_EDGE_BGN || idx >= tmap_len) { - fprintf(MSG_OUT, "idx out of bounds idx=%i %i", idx, tmap_len); - return 0; - } - /* 0x7fffffff unsets discontinuity bit if present */ - *sector = tmap->map_ent[idx] & 0x7fffffff; - return 1; -} - -/* Do a binary search for earlier admap index near find_sector */ -static int32_t dvdnav_admap_search(vobu_admap_t *admap, uint32_t admap_len, - uint32_t find_sector, uint32_t *vobu) { - int32_t adj = 1; - int32_t prv_pos = 0; - int32_t prv_len = admap_len; - int32_t cur_len = 0; - int32_t cur_idx = 0; - uint32_t cur_sector = 0; - while (1) { - cur_len = prv_len / 2; - /* need to add 1 when prv_len == 3 (cur_len shoud go to 2, not 1) */ - if (prv_len % 2 == 1) ++cur_len; - cur_idx = prv_pos + (cur_len * adj); - if (cur_idx < 0) cur_idx = 0; - else if (cur_idx >= admap_len) cur_idx = admap_len - 1; - - cur_sector = admap->vobu_start_sectors[cur_idx]; - if (find_sector < cur_sector) adj = -1; - else if (find_sector > cur_sector) adj = 1; - else if (find_sector == cur_sector) { - *vobu = cur_idx; - return 1; - } - if (cur_len == 1) {/* no smaller intervals left */ - if (adj == -1) {/* last comparison was greater; take lesser */ - cur_idx -= 1; - cur_sector = admap->vobu_start_sectors[cur_idx]; - } - *vobu = cur_idx; - return 1; - } - prv_len = cur_len; - prv_pos = cur_idx; - } -} - -/* Do a binary search for the earlier tmap entry near find_sector */ -static int32_t dvdnav_tmap_search(vts_tmap_t *tmap, uint32_t tmap_len, - uint32_t find_sector, int32_t *tmap_idx, uint32_t *sector) { - int32_t adj = 1; - int32_t prv_pos = 0; - int32_t prv_len = tmap_len; - int32_t result = 0; - int32_t cur_len = 0; - int32_t cur_idx = 0; - uint32_t cur_sector = 0; - while (1) { - cur_len = prv_len / 2; - /* need to add 1 when prv_len == 3 (cur_len shoud go to 2, not 1) */ - if (prv_len % 2 == 1) ++cur_len; - cur_idx = prv_pos + (cur_len * adj); - if (cur_idx < 0) cur_idx = 0; - else if (cur_idx >= tmap_len) cur_idx = tmap_len - 1; - cur_sector = 0; - result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector); - if (!result) return 0; - if (find_sector < cur_sector) adj = -1; - else if (find_sector > cur_sector) adj = 1; - else if (find_sector == cur_sector) { - *tmap_idx = cur_idx; - *sector = cur_sector; - return 1; - } - if (cur_len == 1) {/* no smaller intervals left */ - if (adj == -1) {/* last comparison was greater; take lesser */ - if (cur_idx == 0) { /* fake tmap index for sector 0 */ - cur_idx = TMAP_IDX_EDGE_BGN; - cur_sector = 0; - } - else { - cur_idx -= 1; - result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector); - if (!result) return 0; - } - } - *tmap_idx = cur_idx; - *sector = cur_sector; - return 1; - } - prv_len = cur_len; - prv_pos = cur_idx; - } -} - -/* Find the cell for a given time */ -static int32_t dvdnav_cell_find(dvdnav_t *this, dvd_state_t *state, - uint64_t find_val, dvdnav_cell_data_t *cell_data) { - uint32_t cells_len = 0; - uint32_t cells_bgn = 0; - uint32_t cells_end = 0; - uint32_t cell_idx = 0; - pgc_t *pgc = NULL; - int pgN = 0; - cell_playback_t *cell = NULL; - int found = 0; - - pgc = state->pgc; - if (pgc == NULL) return 0; - cells_len = pgc->nr_of_cells; - if (cells_len == 0) { - fprintf(MSG_OUT, "cells_len == 0"); - return 0; - } - - /* get cells_bgn, cells_end */ - if (this->pgc_based) { - cells_bgn = 1; - cells_end = cells_len; - } - else { - pgN = state->pgN; - cells_bgn = pgc->program_map[pgN - 1]; /* -1 b/c pgN is 1 based? */ - if (pgN < pgc->nr_of_programs) { - cells_end = pgc->program_map[pgN] - 1; - } - else { - cells_end = cells_len; - } - } - - /* search cells */ - for (cell_idx = cells_bgn; cell_idx <= cells_end; cell_idx++) { - cell = &(pgc->cell_playback[cell_idx - 1]); /* -1 b/c cell is base1 */ - /* if angle block, only consider first angleBlock - * (others are "redundant" for purpose of search) */ - if ( cell->block_type == BLOCK_TYPE_ANGLE_BLOCK - && cell->block_mode != BLOCK_MODE_FIRST_CELL) { - continue; - } - cell_data->bgn->sector = cell->first_sector; - cell_data->end->sector = cell->last_sector; - - /* 90 pts to ms */ - cell_data->end->time += (dvdnav_convert_time(&cell->playback_time) / 90); - if ( find_val >= cell_data->bgn->time - && find_val <= cell_data->end->time) { - found = 1; - break; - } - cell_data->bgn->time = cell_data->end->time; - } - - /* found cell: set var */ - if (found) { - cell_data->idx = cell_idx; - } - else - fprintf(MSG_OUT, "cell not found; find=%"PRId64"", find_val); - return found; -} - -/* Given two sectors and a fraction, calc the corresponding vobu */ -static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args, - dvdnav_pos_data_t *bgn, dvdnav_pos_data_t *end, uint32_t fraction, - uint32_t *jump_sector) { - int32_t result = 0; - uint32_t vobu_len = 0; - uint32_t vobu_adj = 0; - uint32_t vobu_idx = 0; - - /* get bgn->vobu_idx */ - result = dvdnav_admap_search(args->admap, args->admap_len, - bgn->sector, &bgn->vobu_idx); - if (!result) { - fprintf(MSG_OUT, "admap_interpolate: could not find sector_bgn"); - return 0; - } - - /* get end->vobu_idx */ - result = dvdnav_admap_search(args->admap, args->admap_len, - end->sector, &end->vobu_idx); - if (!result) { - fprintf(MSG_OUT, "admap_interpolate: could not find sector_end"); - return 0; - } - - vobu_len = end->vobu_idx - bgn->vobu_idx; - /* +500 to round up else 74% of a 4 sec interval = 2 sec */ - vobu_adj = ((fraction * vobu_len) + 500) / 1000; - /* HACK: need to add +1, or else will land too soon (not sure why) */ - vobu_adj++; - vobu_idx = bgn->vobu_idx + vobu_adj; - if (vobu_idx >= args->admap_len) { - fprintf(MSG_OUT, "admap_interpolate: vobu_idx >= admap_len"); - return 0; - } - *jump_sector = args->admap->vobu_start_sectors[vobu_idx]; - return 1; -} - -/* Given two tmap entries and a time, calc the time for the lo tmap entry */ -static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args, - dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi, - dvdnav_pos_data_t *pos, uint64_t *out_time) { - int32_t result = 0; - uint32_t vobu_pct = 0; - uint64_t time_adj = 0; - - if (lo->sector == hi->sector) { - fprintf(MSG_OUT, "lo->sector == hi->sector: %i", lo->sector); - return 0; - } - - /* get vobus corresponding to lo, hi, pos */ - result = dvdnav_admap_search(args->admap, args->admap_len, - lo->sector, &lo->vobu_idx); - if (!result) { - fprintf(MSG_OUT, "lo->vobu: lo->sector=%i", lo->sector); - return 0; - } - result = dvdnav_admap_search(args->admap, args->admap_len, - hi->sector, &hi->vobu_idx); - if (!result) { - fprintf(MSG_OUT, "hi->vobu: hi->sector=%i", hi->sector); - return 0; - } - result = dvdnav_admap_search(args->admap, args->admap_len, - pos->sector, &pos->vobu_idx); - if (!result) { - fprintf(MSG_OUT, "pos->vobu: pos->sector=%i", pos->sector); - return 0; - } - - /* calc position of cell relative to lo */ - vobu_pct = ((pos->vobu_idx - lo->vobu_idx) * 1000) - / ( hi->vobu_idx - lo->vobu_idx); - if (vobu_pct < 0 || vobu_pct > 1000) { - fprintf(MSG_OUT, "vobu_pct must be between 0 and 1000"); - return 0; - } - - /* calc time of lo */ - time_adj = (uint64_t)((args->tmap_interval * vobu_pct) / 1000); - *out_time = pos->time - time_adj; - return 1; -} - -/* Find the tmap entries on either side of a given sector */ -static int32_t dvdnav_tmap_get_entries_for_sector(dvdnav_t *this, - dvd_state_t *state, dvdnav_jump_args_t *args, - dvdnav_cell_data_t *cell_data, uint32_t find_sector, - dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi) { - int32_t result = 0; - - result = dvdnav_tmap_search(args->tmap, args->tmap_len, find_sector, - &lo->tmap_idx, &lo->sector); - if (!result) { - fprintf(MSG_OUT, "could not find lo idx: %i", find_sector); - return 0; - } - - /* HACK: Most DVDs have a tmap that starts at sector 0 - * However, some have initial dummy cells that are not seekable - * (restricted = y). - * These cells will throw off the tmap calcs when in the first playable cell. - * For now, assume that lo->sector is equal to the cell->bgn->sector - * Note that for most DVDs this will be 0 - * (Since they will have no dummy cells and cell 1 will start at sector 0) - */ - if (lo->tmap_idx == TMAP_IDX_EDGE_BGN) { - lo->sector = cell_data->bgn->sector; - } - - if (lo->tmap_idx == args->tmap_len - 1) { - /* lo is last tmap entry; "fake" entry for one beyond - * and mark it with cell_end_sector */ - hi->tmap_idx = TMAP_IDX_EDGE_END; - hi->sector = cell_data->end->sector; - } - else { - hi->tmap_idx = lo->tmap_idx + 1; - result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, - hi->tmap_idx, &hi->sector); - if (!result) { - fprintf(MSG_OUT, "could not find hi idx: %i", find_sector); - return 0; - } - } - return 1; -} - -/* Find the nearest vobu by using the tmap */ -static int32_t dvdnav_find_vobu_by_tmap(dvdnav_t *this, dvd_state_t *state, - dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data, - dvdnav_pos_data_t *jump) { - uint64_t seek_offset = 0; - uint32_t seek_idx = 0; - int32_t result = 0; - dvdnav_pos_data_t *cell_bgn_lo = NULL; - dvdnav_pos_data_t *cell_bgn_hi = NULL; - dvdnav_pos_data_t *jump_lo = NULL; - dvdnav_pos_data_t *jump_hi = NULL; - - /* get tmap, tmap_len, tmap_interval */ - args->tmap = dvdnav_tmap_get(this, state, - &args->tmap_len, &args->tmap_interval); - if (args->tmap == NULL) return 0; - - /* get tmap entries on either side of cell_bgn */ - cell_bgn_lo = &(dvdnav_pos_data_t){0}; - cell_bgn_hi = &(dvdnav_pos_data_t){0}; - result = dvdnav_tmap_get_entries_for_sector(this, state, args, cell_data, - cell_data->bgn->sector, cell_bgn_lo, cell_bgn_hi); - if (!result) return 0; - - /* calc time of cell_bgn_lo */ - result = dvdnav_tmap_calc_time_for_tmap_entry(args, cell_bgn_lo, cell_bgn_hi, - cell_data->bgn, &cell_bgn_lo->time); - if (!result) return 0; - - /* calc time of jump_time relative to cell_bgn_lo */ - seek_offset = jump->time - cell_bgn_lo->time; - seek_idx = (uint32_t)(seek_offset / args->tmap_interval); - uint32_t seek_remainder = seek_offset - (seek_idx * args->tmap_interval); - uint32_t seek_pct = (seek_remainder * 1000) / args->tmap_interval; - - /* get tmap entries on either side of jump_time */ - jump_lo = &(dvdnav_pos_data_t){0}; - jump_hi = &(dvdnav_pos_data_t){0}; - - /* if seek_idx == 0, then tmap_indexes are the same, do not re-get - * also, note cell_bgn_lo will already have sector if TMAP_IDX_EDGE_BGN */ - if (seek_idx == 0) { - jump_lo = cell_bgn_lo; - jump_hi = cell_bgn_hi; - } - else { - jump_lo->tmap_idx = (uint32_t)(cell_bgn_lo->tmap_idx + seek_idx); - result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, - jump_lo->tmap_idx, &jump_lo->sector); - if (!result) return 0; - - /* +1 handled by dvdnav_tmap_get_entry */ - jump_hi->tmap_idx = jump_lo->tmap_idx + 1; - result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, - jump_hi->tmap_idx, &jump_hi->sector); - if (!result) return 0; - } - - /* interpolate sector */ - result = dvdnav_admap_interpolate_vobu(args, jump_lo, jump_hi, - seek_pct, &jump->sector); - - return result; -} - -/* Find the nearest vobu by using the cell boundaries */ -static int32_t dvdnav_find_vobu_by_cell_boundaries(dvdnav_t *this, - dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data, - dvdnav_pos_data_t *jump) { - uint64_t jump_offset = 0; - uint64_t cell_len = 0; - uint32_t jump_pct = 0; - int32_t result = 0; - - /* get jump_offset */ - jump_offset = jump->time - cell_data->bgn->time; - if (jump_offset < 0) { - fprintf(MSG_OUT, "jump_offset < 0"); - return 0; - } - cell_len = cell_data->end->time - cell_data->bgn->time; - if (cell_len < 0) { - fprintf(MSG_OUT, "cell_len < 0"); - return 0; - } - jump_pct = (jump_offset * 1000) / cell_len; - - /* get sector */ - /* NOTE: end cell sector in VTS_PGC is last sector of cell - * this last sector is not the start of a VOBU - * +1 to get sector that is the start of a VOBU - * start of a VOBU is needed in order to index into admap */ - cell_data->end->sector += 1; - result = dvdnav_admap_interpolate_vobu(args, - cell_data->bgn, cell_data->end, jump_pct, &jump->sector); - if (!result) { - fprintf(MSG_OUT, "find_by_admap.interpolate"); - return 0; - } - return 1; -} - -/* Jump to sector by time */ -/* NOTE: Mode is currently unimplemented. Only 0 should be passed. */ -/* 1 and -1 are for future implementation */ -/* 0: Default. Jump to a time which may be either <> time_in_pts_ticks */ -/* 1: After. Always jump to a time that is > time_in_pts_ticks */ -/* -1: Before. Always jump to a time that is < time_in_pts_ticks */ -dvdnav_status_t dvdnav_jump_to_sector_by_time(dvdnav_t *this, - uint64_t time_in_pts_ticks, int32_t mode) { - if (mode != JUMP_MODE_TIME_DEFAULT) return DVDNAV_STATUS_ERR; - int32_t result = DVDNAV_STATUS_ERR; - dvd_state_t *state = NULL; - uint32_t sector_off = 0; - dvdnav_pos_data_t *jump = NULL; - dvdnav_cell_data_t *cell_data = NULL; - dvdnav_jump_args_t *args = NULL; - - jump = &(dvdnav_pos_data_t){0}; - /* convert time to milliseconds */ - jump->time = time_in_pts_ticks / 90; - - /* get variables that will be used across both functions */ - state = &(this->vm->state); - if (state == NULL) goto exit; - - /* get cell info */ - cell_data = &(dvdnav_cell_data_t){0}; - cell_data->bgn = &(dvdnav_pos_data_t){0}; - cell_data->end = &(dvdnav_pos_data_t){0}; - result = dvdnav_cell_find(this, state, jump->time, cell_data); - if (!result) goto exit; - - /* get admap */ - args = &(dvdnav_jump_args_t){0}; - args->admap = dvdnav_admap_get(this, state, &args->admap_len); - if (args->admap == NULL) goto exit; - - /* find sector */ - result = dvdnav_find_vobu_by_tmap(this, state, args, cell_data, jump); - if (!result) {/* bad tmap; interpolate over cell */ - result = dvdnav_find_vobu_by_cell_boundaries(this, args, cell_data, jump); - if (!result) { - goto exit; - } - } - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: seeking to time=%lu\n", jump->time); - fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); -#endif - - /* jump to sector */ - sector_off = jump->sector - cell_data->bgn->sector; - this->cur_cell_time = 0; - if (vm_jump_cell_block(this->vm, cell_data->idx, sector_off)) { - pthread_mutex_lock(&this->vm_lock); - this->vm->hop_channel += HOP_SEEK; - pthread_mutex_unlock(&this->vm_lock); - result = DVDNAV_STATUS_OK; - } - -#ifdef LOG_DEBUG - fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u\n", state->cellN, state->blockN); -#endif - -exit: - return result; -} |