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

📄 vm.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 4 页
字号:
      do_nothing.data1 = state.blockN;      link_values = do_nothing;    }  }    *link_return = link_values;  return 1; // Success}int vm_resume(void){  link_t link_values;    if(!vm_resume_int(&link_values))    return 0;    link_values = process_command(link_values);  assert(link_values.command == PlayThis);  state.blockN = link_values.data1;  return 1; // Jump}/** * Return the substream id for 'logical' audio stream audioN. *  0 <= audioN < 8 */int vm_get_audio_stream(int audioN){  int streamN = -1;    if(state.domain == VTSM_DOMAIN      || state.domain == VMGM_DOMAIN     || state.domain == FP_DOMAIN) {    audioN = 0;  }    if(audioN < 8) {    /* Is there any contol info for this logical stream */     if(state.pgc->audio_control[audioN] & (1<<15)) {      streamN = (state.pgc->audio_control[audioN] >> 8) & 0x07;      }  }    if(state.domain == VTSM_DOMAIN      || state.domain == VMGM_DOMAIN     || state.domain == FP_DOMAIN) {    if(streamN == -1)      streamN = 0;  }    return streamN;}/** * Return the substream id for 'logical' subpicture stream subpN. * 0 <= subpN < 32 */int vm_get_subp_stream(int subpN){  int streamN = -1;  int source_aspect = get_video_aspect();    if(state.domain == VTSM_DOMAIN      || state.domain == VMGM_DOMAIN     || state.domain == FP_DOMAIN) {    subpN = 0;  }    if(subpN < 32) { /* a valid logical stream */    /* Is this logical stream present */     if(state.pgc->subp_control[subpN] >> 31) {      if(source_aspect == 0) /* 4:3 */	     	streamN = (state.pgc->subp_control[subpN] >> 24) & 0x1f;        if(source_aspect == 3) /* 16:9 */	streamN = (state.pgc->subp_control[subpN] >> 16) & 0x1f;    }  }    /* Paranoia.. if no stream select 0 anyway */  if(state.domain == VTSM_DOMAIN      || state.domain == VMGM_DOMAIN     || state.domain == FP_DOMAIN) {    if(streamN == -1)      streamN = 0;  }  return streamN;}int vm_get_subp_active_stream(void){  int subpN = state.SPST_REG & ~0x40;  int streamN = vm_get_subp_stream(subpN);    /* If no such stream, then select the first one that exists. */  if(streamN == -1)    for(subpN = 0; subpN < 32; subpN++)      if(state.pgc->subp_control[subpN] >> 31) {	streamN = vm_get_subp_stream(subpN);	break;      }    /* We should instead send the on/off status to the spudecoder / mixer */  /* If we are in the title domain see if the spu mixing is on */  if(state.domain == VTS_DOMAIN && !(state.SPST_REG & 0x40)) {     return -1;  } else {    return streamN;  }}void vm_get_angle_info(int *num_avail, int *current){  *num_avail = 1;  *current = 1;    if(state.domain == VTS_DOMAIN) {    // TTN_REG does not allways point to the correct title..    title_info_t *title;    if(state.TTN_REG > vmgi->tt_srpt->nr_of_srpts)      return;    title = &vmgi->tt_srpt->title[state.TTN_REG - 1];    if(title->title_set_nr != state.vtsN ||        title->vts_ttn != state.VTS_TTN_REG)      return;     *num_avail = title->nr_of_angles;    *current = state.AGL_REG;    if(*current > *num_avail) // Is this really a good idee?      *current = *num_avail;   }}void vm_get_audio_info(int *num_avail, int *current){  if(state.domain == VTS_DOMAIN) {    *num_avail = vtsi->vtsi_mat->nr_of_vts_audio_streams;    *current = state.AST_REG;  } else if(state.domain == VTSM_DOMAIN) {    *num_avail = vtsi->vtsi_mat->nr_of_vtsm_audio_streams; // 1    *current = 1;  } else if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN) {    *num_avail = vmgi->vmgi_mat->nr_of_vmgm_audio_streams; // 1    *current = 1;  }}void vm_get_subp_info(int *num_avail, int *current){  if(state.domain == VTS_DOMAIN) {    *num_avail = vtsi->vtsi_mat->nr_of_vts_subp_streams;    *current = state.SPST_REG;  } else if(state.domain == VTSM_DOMAIN) {    *num_avail = vtsi->vtsi_mat->nr_of_vtsm_subp_streams; // 1    *current = 0x41;  } else if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN) {    *num_avail = vmgi->vmgi_mat->nr_of_vmgm_subp_streams; // 1    *current = 0x41;  }}int vm_get_domain(void){  /* The enum for this domain the one in the dvdcontrol interface   * (ogle/dvd.h) are in sync, so no coversion is necessary.  */  return state.domain;}void vm_get_volume_info(int *nrofvolumes,int *volume,int *side,int *nroftitles){ *nrofvolumes = vmgi->vmgi_mat->vmg_nr_of_volumes; *volume = vmgi->vmgi_mat->vmg_this_volume_nr; *side = vmgi->vmgi_mat->disc_side; *nroftitles = vmgi->vmgi_mat->vmg_nr_of_title_sets;}int vm_get_titles(void){ int titles = 0; titles = vmgi->tt_srpt->nr_of_srpts; return titles;}int vm_get_ptts_for_title(int titleN){ int ptts = 0; if(titleN <= vmgi->tt_srpt->nr_of_srpts) {   ptts = vmgi->tt_srpt->title[titleN - 1].nr_of_ptts; } return ptts;}subp_attr_t vm_get_subp_attr(int streamN){  subp_attr_t attr;    if(state.domain == VTS_DOMAIN) {    attr = vtsi->vtsi_mat->vts_subp_attr[streamN];  } else if(state.domain == VTSM_DOMAIN) {    attr = vtsi->vtsi_mat->vtsm_subp_attr;  } else if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN) {    attr = vmgi->vmgi_mat->vmgm_subp_attr;  }  return attr;}user_ops_t vm_get_uops(void){  return state.pgc->prohibited_ops;}audio_attr_t vm_get_audio_attr(int streamN){  audio_attr_t attr;  if(state.domain == VTS_DOMAIN) {    attr = vtsi->vtsi_mat->vts_audio_attr[streamN];  } else if(state.domain == VTSM_DOMAIN) {    attr = vtsi->vtsi_mat->vtsm_audio_attr;  } else if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN) {    attr = vmgi->vmgi_mat->vmgm_audio_attr;  }  return attr;}video_attr_t vm_get_video_attr(void){  video_attr_t attr;    if(state.domain == VTS_DOMAIN) {    attr = vtsi->vtsi_mat->vts_video_attr;  } else if(state.domain == VTSM_DOMAIN) {    attr = vtsi->vtsi_mat->vtsm_video_attr;  } else if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN) {    attr = vmgi->vmgi_mat->vmgm_video_attr;  }  return attr;}void vm_get_video_res(int *width, int *height){  video_attr_t attr;    attr = vm_get_video_attr();    if(attr.video_format != 0)     *height = 576;  else    *height = 480;  switch(attr.picture_size) {  case 0:    *width = 720;    break;  case 1:    *width = 704;    break;  case 2:    *width = 352;    break;  case 3:    *width = 352;    *height /= 2;    break;  }}unsigned int bcd2int(unsigned int bcd){  unsigned int pot = 1;   unsigned int res = 0;   while(bcd != 0) {    res += (bcd & 0x0f) * pot;    bcd >>= 4;    pot *= 10;  }  return res;}unsigned int int2bcd(unsigned int number){  unsigned int pot = 1;   unsigned int res = 0;   while(number != 0) {    res += (number % 10) * pot;    number /= 10;    pot <<= 4;  }  return res;}static unsigned int time2sec(dvd_time_t *time){  unsigned int acc_s;    // convert from bcd to seconds  acc_s = bcd2int(time->hour) * 60 * 60;  acc_s += bcd2int(time->minute) * 60;  acc_s += bcd2int(time->second);    /*  frames = bcd2int(time->frame_u & 0x3f);  switch(acc->frame_u >> 6) {  case 1:    frame_rate = 25;    break;  case 3:    frame_rate = 30; // 29.97    break;  default:    frame_rate = 30; // ??    break;  }  // normalize time, should we round to nearest? (+ frame_rate/2)  acc_s += frames / frame_rate;  */    return acc_s;}static void time_add(dvd_time_t *acc, const dvd_time_t *diff){  unsigned int acc_s, diff_s;  int frame_rate, frames;    if((acc->frame_u & 0xc0) != (diff->frame_u & 0xc0)) {    // argh.. frame rates differ.. what?!?    // at most it will cause 5/25 fault for each addition    DNOTE("frame rates differ in time_add %i %i\n", 	  acc->frame_u>>6, diff->frame_u>>6);  }  // convert from bcd to seconds  acc_s = bcd2int(acc->hour) * 60 * 60;  acc_s += bcd2int(acc->minute) * 60;  acc_s += bcd2int(acc->second);    diff_s = bcd2int(diff->hour) * 60 * 60;  diff_s += bcd2int(diff->minute) * 60;  diff_s += bcd2int(diff->second);    // add time  acc_s += diff_s;    frames = bcd2int(acc->frame_u & 0x3f) + bcd2int(diff->frame_u & 0x3f);  switch(acc->frame_u >> 6) {  case 1:    frame_rate = 25;    break;  case 3:    frame_rate = 30; // 29.97    break;  default:    frame_rate = 30; // ??    break;  }     // normalize time  acc_s += frames / frame_rate;  // convert back to bcd  acc->frame_u = int2bcd(frames % frame_rate) | (acc->frame_u & 0xc0);  acc->second = int2bcd(acc_s % 60);  acc->minute = int2bcd((acc_s / 60) % 60);  acc->hour   = int2bcd(acc_s / (60 * 60));}void vm_get_total_time(dvd_time_t *current_time){  *current_time = state.pgc->playback_time;  /* This should give the same time as well.... */  //vm_get_cell_start_time(current_time, state.pgc->nr_of_cells);}void vm_get_current_time(dvd_time_t *current_time, dvd_time_t *cell_elapsed){  vm_get_cell_start_time(current_time, state.cellN);  /* Add the time within the cell. */  time_add(current_time, cell_elapsed);}/* Should return status info or something... */void vm_get_cell_start_time(dvd_time_t *current_time, int cellN){  dvd_time_t angle_time;  playback_type_t *pb_ty;  cell_playback_t *const cell_pb = state.pgc->cell_playback;  int i;    current_time->hour = 0;  current_time->minute = 0;  current_time->second = 0;  /* Frame code */  current_time->frame_u = state.pgc->playback_time.frame_u & 0xc0;      /* Should only be called for One_Sequential_PGC_Title PGCs. */  if(state.domain != VTS_DOMAIN) {    /* No time info */    return;  }  pb_ty = &vmgi->tt_srpt->title[state.TTN_REG - 1].pb_ty;  if(pb_ty->multi_or_random_pgc_title != /* One_Sequential_PGC_Title */ 0) {    /*No time info */    return;  }    assert(cellN <= state.pgc->nr_of_cells);    for(i = 1; i < cellN; i++) {        /* Multi angle/Interleaved */    switch(cell_pb[i - 1].block_mode) {    case BLOCK_MODE_NOT_IN_BLOCK:      assert(cell_pb[i - 1].block_type == BLOCK_TYPE_NONE);      time_add(current_time, &cell_pb[i - 1].playback_time);      break;    case BLOCK_MODE_FIRST_CELL:      switch(cell_pb[i - 1].block_type) {      case BLOCK_TYPE_NONE:	assert(0);      case BLOCK_TYPE_ANGLE_BLOCK:	time_add(current_time, &cell_pb[i - 1].playback_time);	angle_time = cell_pb[i - 1].playback_time;	break;      case 2: // ??      case 3: // ??      default:	WARNING("Invalid? Cell block_mode (%d), block_type (%d)\n",		cell_pb[i - 1].block_mode, cell_pb[i - 1].block_type);      }      break;    case BLOCK_MODE_IN_BLOCK:    case BLOCK_MODE_LAST_CELL:      /* Check that the cells for each angle have equal duration. */      /* THEY WON'T !! */      assert(!memcmp(&angle_time, 		     &cell_pb[i - 1].playback_time, sizeof(dvd_time_t)));      break;    default:      WARNING("%s", "Cell is in block but did not enter at first cell!\n");    }  }}// Must be called before domain is changed (get_PGCN())static void saveRSMinfo(int cellN, int blockN){  int i;    if(cellN != 0) {    state.rsm_cellN = cellN;    state.rsm_blockN = 0;  } else {    state.rsm_cellN = state.cellN;    state.rsm_blockN = blockN;  }  state.rsm_vtsN = state.vtsN;  state.rsm_pgcN = get_PGCN();

⌨️ 快捷键说明

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