⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 searching.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * * $Id: searching.c,v 1.20 2006/09/17 13:01:08 valtri Exp $ * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <assert.h>#include "dvdnav_internal.h"#include "dvdnav.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, 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;    int32_t found = 0;    /* Search through ADMAP for best sector */    vobu_start = SRI_END_OF_CELL;    /* FIXME: Implement a faster search algorithm */    while((!found) && ((address<<2) < admap->last_byte)) {      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) {        found = 1;      } else {        vobu_start = next_vobu;      }      address ++;    }    if(found) {      *vobu = vobu_start;      return DVDNAV_STATUS_OK;    } else {      fprintf(MSG_OUT, "libdvdnav: Could not locate block\n");      return DVDNAV_STATUS_ERR;    }  }  fprintf(MSG_OUT, "libdvdnav: admap not located\n");  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;  }    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;  uint32_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;  }    result = dvdnav_get_position(this, &target, &length);  if(!result) {    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=%lu pos=%u length=%u\n", offset, target, length);   fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN);#endif  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 < 0) {      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;  }    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 = 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;      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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -