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

📄 vm.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> *               2002-2004 the dvdnav project *  * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. *  * 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: vm.c,v 1.32 2004/12/20 19:27:20 mroi Exp $ * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <inttypes.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "ifo_types.h"#include "ifo_read.h"#include "dvdnav_internal.h"#ifdef _MSC_VER#include <io.h>   /* read() */#endif /* _MSC_VER *//*#define STRICT*//* Local prototypes *//* get_XYZ returns a value. * set_XYZ sets state using passed parameters. *         returns success/failure. *//* Play */static link_t play_PGC(vm_t *vm);static link_t play_PGC_PG(vm_t *vm, int pgN);static link_t play_PGC_post(vm_t *vm);static link_t play_PG(vm_t *vm);static link_t play_Cell(vm_t *vm);static link_t play_Cell_post(vm_t *vm);/* Process link - returns 1 if a hop has been performed */static int process_command(vm_t *vm,link_t link_values);/* Set */static int  set_TT(vm_t *vm, int tt);static int  set_PTT(vm_t *vm, int tt, int ptt);static int  set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn);static int  set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part);static int  set_FP_PGC(vm_t *vm);static int  set_MENU(vm_t *vm, int menu);static int  set_PGCN(vm_t *vm, int pgcN);static int  set_PGN(vm_t *vm); /* Set PGN based on (vm->state).CellN */static void set_RSMinfo(vm_t *vm, int cellN, int blockN);/* Get */static int get_TT(vm_t *vm, int vtsN, int vts_ttn);static int get_ID(vm_t *vm, int id);static int get_PGCN(vm_t *vm);static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang);static pgcit_t* get_PGCIT(vm_t *vm);/* Helper functions */#ifdef TRACEstatic void vm_print_current_domain_state(vm_t *vm) {  switch((vm->state).domain) {    case VTS_DOMAIN:      fprintf(MSG_OUT, "libdvdnav: Video Title Domain: -\n");      break;    case VTSM_DOMAIN:      fprintf(MSG_OUT, "libdvdnav: Video Title Menu Domain: -\n");      break;    case VMGM_DOMAIN:      fprintf(MSG_OUT, "libdvdnav: Video Manager Menu Domain: -\n");      break;    case FP_DOMAIN:       fprintf(MSG_OUT, "libdvdnav: First Play Domain: -\n");      break;    default:      fprintf(MSG_OUT, "libdvdnav: Unknown Domain: -\n");      break;  }  fprintf(MSG_OUT, "libdvdnav: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n",                    (vm->state).vtsN,                   get_PGCN(vm),                   (vm->state).pgN,                   (vm->state).cellN,                   (vm->state).blockN,                   (vm->state).VTS_TTN_REG,                   (vm->state).TTN_REG,                   (vm->state).TT_PGCN_REG);}#endifstatic void dvd_read_name(char *name, const char *device) {    /* Because we are compiling with _FILE_OFFSET_BITS=64     * all off_t are 64bit.     */    off_t off;    int fd, i;    uint8_t data[DVD_VIDEO_LB_LEN];    /* Read DVD name */    fd = open(device, O_RDONLY);    if (fd > 0) {       off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET );      if( off == ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {        off = read( fd, data, DVD_VIDEO_LB_LEN );         close(fd);        if (off == ( (off_t) DVD_VIDEO_LB_LEN )) {          fprintf(MSG_OUT, "libdvdnav: DVD Title: ");          for(i=25; i < 73; i++ ) {            if((data[i] == 0)) break;            if((data[i] > 32) && (data[i] < 127)) {              fprintf(MSG_OUT, "%c", data[i]);            } else {              fprintf(MSG_OUT, " ");            }          }          strncpy(name, &data[25], 48);          name[48] = 0;          fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");          for(i=73; i < 89; i++ ) {            if((data[i] == 0)) break;            if((data[i] > 32) && (data[i] < 127)) {              fprintf(MSG_OUT, "%c", data[i]);            } else {              fprintf(MSG_OUT, " ");            }           }          fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");          for(i=89; i < 128; i++ ) {            if((data[i] == 0)) break;            if((data[i] > 32) && (data[i] < 127)) {              fprintf(MSG_OUT, "%c", data[i]);            } else {              fprintf(MSG_OUT, " ");            }          }          fprintf(MSG_OUT, "\n");        } else {          fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");        }      } else {        fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );      }      close(fd);    } else {    fprintf(MSG_OUT, "NAME OPEN FAILED\n");  }}static int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {  if((vm->state).vtsN == vtsN) {    return 1; /*  We alread have it */  }    if(vm->vtsi != NULL)    ifoClose(vm->vtsi);    vm->vtsi = ifoOpenVTSI(dvd, vtsN);  if(vm->vtsi == NULL) {    fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed\n");    return 0;  }  if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) {    fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed\n");    return 0;  }  if(!ifoRead_PGCIT(vm->vtsi)) {    fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed\n");    return 0;  }  if(!ifoRead_PGCI_UT(vm->vtsi)) {    fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed\n");    return 0;  }  if(!ifoRead_VOBU_ADMAP(vm->vtsi)) {    fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed\n");    return 0;  }  if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) {    fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed\n");    return 0;  }  (vm->state).vtsN = vtsN;    return 1;}/* Initialisation & Destruction */vm_t* vm_new_vm() {  return (vm_t*)calloc(sizeof(vm_t), sizeof(char));}void vm_free_vm(vm_t *vm) {  vm_stop(vm);  free(vm);}/* IFO Access */ifo_handle_t *vm_get_vmgi(vm_t *vm) {  return vm->vmgi;}ifo_handle_t *vm_get_vtsi(vm_t *vm) {  return vm->vtsi;}/* Reader Access */dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {  return vm->dvd;}/* Basic Handling */int vm_start(vm_t *vm) {  /* Set pgc to FP (First Play) pgc */  set_FP_PGC(vm);  process_command(vm, play_PGC(vm));  return !vm->stopped;}void vm_stop(vm_t *vm) {  if(vm->vmgi) {    ifoClose(vm->vmgi);    vm->vmgi=NULL;  }  if(vm->vtsi) {    ifoClose(vm->vtsi);    vm->vtsi=NULL;  }  if(vm->dvd) {    DVDClose(vm->dvd);    vm->dvd=NULL;  }  vm->stopped = 1;} int vm_reset(vm_t *vm, const char *dvdroot) {  /*  Setup State */  memset((vm->state).registers.SPRM, 0, sizeof((vm->state).registers.SPRM));  memset((vm->state).registers.GPRM, 0, sizeof((vm->state).registers.GPRM));  memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));  memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));  memset((vm->state).registers.GPRM_time, 0, sizeof((vm->state).registers.GPRM_time));  (vm->state).registers.SPRM[0]  = ('e'<<8)|'n'; /* Player Menu Languange code */  (vm->state).AST_REG            = 15;           /* 15 why? */  (vm->state).SPST_REG           = 62;           /* 62 why? */  (vm->state).AGL_REG            = 1;  (vm->state).TTN_REG            = 1;  (vm->state).VTS_TTN_REG        = 1;  /* (vm->state).TT_PGCN_REG        = 0 */  (vm->state).PTTN_REG           = 1;  (vm->state).HL_BTNN_REG        = 1 << 10;  (vm->state).PTL_REG            = 15;           /* Parental Level */  (vm->state).registers.SPRM[12] = ('U'<<8)|'S'; /* Parental Management Country Code */  (vm->state).registers.SPRM[16] = ('e'<<8)|'n'; /* Initial Language Code for Audio */  (vm->state).registers.SPRM[18] = ('e'<<8)|'n'; /* Initial Language Code for Spu */  (vm->state).registers.SPRM[20] = 0x1;          /* Player Regional Code Mask. Region free! */  (vm->state).registers.SPRM[14] = 0x100;        /* Try Pan&Scan */     (vm->state).pgN                = 0;  (vm->state).cellN              = 0;  (vm->state).cell_restart       = 0;  (vm->state).domain             = FP_DOMAIN;  (vm->state).rsm_vtsN           = 0;  (vm->state).rsm_cellN          = 0;  (vm->state).rsm_blockN         = 0;    (vm->state).vtsN               = -1;    if (vm->dvd && dvdroot) {    /* a new dvd device has been requested */    vm_stop(vm);  }  if (!vm->dvd) {    vm->dvd = DVDOpen(dvdroot);    if(!vm->dvd) {      fprintf(MSG_OUT, "libdvdnav: vm: faild to open/read the DVD\n");      return 0;    }    dvd_read_name(vm->dvd_name, dvdroot);    vm->map  = remap_loadmap(vm->dvd_name);    vm->vmgi = ifoOpenVMGI(vm->dvd);    if(!vm->vmgi) {      fprintf(MSG_OUT, "libdvdnav: vm: faild to read VIDEO_TS.IFO\n");      return 0;    }    if(!ifoRead_FP_PGC(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_FP_PGC failed\n");      return 0;    }    if(!ifoRead_TT_SRPT(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_TT_SRPT failed\n");      return 0;    }    if(!ifoRead_PGCI_UT(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PGCI_UT failed\n");      return 0;    }    if(!ifoRead_PTL_MAIT(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PTL_MAIT failed\n");      /* return 0; Not really used for now.. */    }    if(!ifoRead_VTS_ATRT(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VTS_ATRT failed\n");      /* return 0; Not really used for now.. */    }    if(!ifoRead_VOBU_ADMAP(vm->vmgi)) {      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n");      /* return 0; Not really used for now.. */    }    /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */  }  if (vm->vmgi) {    int i, mask;    fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:",      vm->vmgi->vmgi_mat->vmg_category);    for (i = 1, mask = 1; i <= 8; i++, mask <<= 1)      if (((vm->vmgi->vmgi_mat->vmg_category >> 16) & mask) == 0)        fprintf(MSG_OUT, " %d", i);    fprintf(MSG_OUT, "\n");  }  return 1;}/* copying and merging */vm_t *vm_new_copy(vm_t *source) {  vm_t *target = vm_new_vm();  int vtsN;  int pgcN = get_PGCN(source);  int pgN  = (source->state).pgN;    assert(pgcN);    memcpy(target, source, sizeof(vm_t));    /* open a new vtsi handle, because the copy might switch to another VTS */  target->vtsi = NULL;  vtsN = (target->state).vtsN;  if (vtsN > 0) {    (target->state).vtsN = 0;    if (!ifoOpenNewVTSI(target, target->dvd, vtsN))      assert(0);      /* restore pgc pointer into the new vtsi */    if (!set_PGCN(target, pgcN))      assert(0);    (target->state).pgN = pgN;  }    return target;}void vm_merge(vm_t *target, vm_t *source) {  if(target->vtsi)    ifoClose(target->vtsi);  memcpy(target, source, sizeof(vm_t));  memset(source, 0, sizeof(vm_t));}void vm_free_copy(vm_t *vm) {  if(vm->vtsi)    ifoClose(vm->vtsi);  free(vm);}/* regular playback */void vm_position_get(vm_t *vm, vm_position_t *position) {  position->button = (vm->state).HL_BTNN_REG >> 10;  position->vts = (vm->state).vtsN;   position->domain = (vm->state).domain;   position->spu_channel = (vm->state).SPST_REG;  position->audio_channel = (vm->state).AST_REG;  position->angle_channel = (vm->state).AGL_REG;  position->hop_channel = vm->hop_channel; /* Increases by one on each hop */  position->cell = (vm->state).cellN;  position->cell_restart = (vm->state).cell_restart;  position->cell_start = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector;  position->still = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].still_time;  position->block = (vm->state).blockN;  /* handle PGC stills at PGC end */  if ((vm->state).cellN == (vm->state).pgc->nr_of_cells)    position->still += (vm->state).pgc->still_time;  /* still already determined */  if (position->still)    return;  /* This is a rough fix for some strange still situations on some strange DVDs.   * There are discs (like the German "Back to the Future" RC2) where the only   * indication of a still is a cell playback time higher than the time the frames   * in this cell actually take to play (like 1 frame with 1 minute playback time).   * On the said BTTF disc, for these cells last_sector and last_vobu_start_sector   * are equal and the cells are very short, so we abuse these conditions to   * detect such discs. I consider these discs broken, so the fix is somewhat   * broken, too. */  if (((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector ==       (vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_vobu_start_sector) &&      ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector -       (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector < 1024)) {    int time;    int size = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector -	       (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector;    time  = ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour   >> 4  ) * 36000;    time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour   & 0x0f) * 3600;    time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute >> 4  ) * 600;    time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute & 0x0f) * 60;    time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second >> 4  ) * 10;    time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second & 0x0f) * 1;    if (!time || size / time > 30)      /* datarate is too high, it might be a very short, but regular cell */      return;    if (time > 0xff) time = 0xff;    position->still = time;  }}void vm_get_next_cell(vm_t *vm) {

⌨️ 快捷键说明

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