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

📄 dvdnav.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * These are the main get_next_block function which actually get the media stream video and audio etc. * * There are two versions: The second one is using the zero-copy read ahead cache and therefore * hands out pointers targetting directly into the cache. * The first one uses a memcopy to fill this cache block into the application provided memory. * The benefit of this first one is that no special memory management is needed. The application is * the only one responsible of allocating and freeing the memory associated with the pointer. * The drawback is the additional memcopy. */dvdnav_status_t dvdnav_get_next_block(dvdnav_t *this, uint8_t *buf,				      int32_t *event, int32_t *len) {  unsigned char *block;  dvdnav_status_t status;    block = buf;  status = dvdnav_get_next_cache_block(this, &block, event, len);  if (status == DVDNAV_STATUS_OK && block != buf) {    /* we received a block from the cache, copy it, so we can give it back */    memcpy(buf, block, DVD_VIDEO_LB_LEN);    dvdnav_free_cache_block(this, block);  }  return status;} dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,					    int32_t *event, int32_t *len) {  dvd_state_t *state;  int32_t result;  if(!this || !event || !len || !buf || !*buf) {    printerr("Passed a NULL pointer.");    return DVDNAV_STATUS_ERR;  }  pthread_mutex_lock(&this->vm_lock);    if(!this->started) {    /* Start the VM */    if (!vm_start(this->vm)) {      printerr("Encrypted or faulty DVD");      return DVDNAV_STATUS_ERR;    }    this->started = 1;  }  state = &(this->vm->state);  (*event) = DVDNAV_NOP;  (*len) = 0;   /* Check the STOP flag */  if(this->vm->stopped) {    vm_stop(this->vm);    (*event) = DVDNAV_STOP;    this->started = 0;    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  vm_position_get(this->vm, &this->position_next);  #ifdef LOG_DEBUG  fprintf(MSG_OUT, "libdvdnav: POS-NEXT ");  vm_position_print(this->vm, &this->position_next);  fprintf(MSG_OUT, "libdvdnav: POS-CUR  ");  vm_position_print(this->vm, &this->position_current);#endif  /* did we hop? */  if(this->position_current.hop_channel != this->position_next.hop_channel) {    (*event) = DVDNAV_HOP_CHANNEL;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: HOP_CHANNEL\n");#endif    if (this->position_next.hop_channel - this->position_current.hop_channel >= HOP_SEEK) {      int32_t num_angles = 0, current;            /* we seeked -> check for multiple angles */      vm_get_angle_info(this->vm, &current, &num_angles);      if (num_angles > 1) {        int32_t result, block;	/* we have to skip the first VOBU when seeking in a multiangle feature,	 * because it might belong to the wrong angle */	block = this->position_next.cell_start + this->position_next.block;	result = dvdnav_read_cache_block(this->cache, block, 1, buf);	if(result <= 0) {	  printerr("Error reading NAV packet.");	  pthread_mutex_unlock(&this->vm_lock); 	  return DVDNAV_STATUS_ERR;	}	/* Decode nav into pci and dsi. Then get next VOBU info. */	if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) {	  printerr("Expected NAV packet but none found.");	  pthread_mutex_unlock(&this->vm_lock); 	  return DVDNAV_STATUS_ERR;	}	dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu);	/* skip to next, if there is a next */	if (this->vobu.vobu_next != SRI_END_OF_CELL) {	  this->vobu.vobu_start += this->vobu.vobu_next;	  this->vobu.vobu_next   = 0;	}	/* update VM state */	this->vm->state.blockN = this->vobu.vobu_start - this->position_next.cell_start;      }    }    this->position_current.hop_channel = this->position_next.hop_channel;    /* update VOBU info */    this->vobu.vobu_start  = this->position_next.cell_start + this->position_next.block;    this->vobu.vobu_next   = 0;    /* Make blockN == vobu_length to do expected_nav */    this->vobu.vobu_length = 0;    this->vobu.blockN      = 0;    this->sync_wait        = 0;    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  /* Check the HIGHLIGHT flag */  if(this->position_current.button != this->position_next.button) {    dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t *)*buf;    (*event) = DVDNAV_HIGHLIGHT;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: HIGHLIGHT\n");#endif    (*len) = sizeof(dvdnav_highlight_event_t);    hevent->display = 1;    hevent->buttonN = this->position_next.button;    this->position_current.button = this->position_next.button;    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }    /* Check the WAIT flag */  if(this->sync_wait) {    (*event) = DVDNAV_WAIT;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: WAIT\n");#endif    (*len) = 0;    pthread_mutex_unlock(&this->vm_lock);    return DVDNAV_STATUS_OK;  }  /* Check to see if we need to change the currently opened VOB */  if((this->position_current.vts != this->position_next.vts) ||      (this->position_current.domain != this->position_next.domain)) {    dvd_read_domain_t domain;    int32_t vtsN;    dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)*buf;        if(this->file) {      DVDCloseFile(this->file);      this->file = NULL;    }    vts_event->old_vtsN = this->position_current.vts;    vts_event->old_domain = this->position_current.domain;         /* Use the DOMAIN to find whether to open menu or title VOBs */    switch(this->position_next.domain) {    case FP_DOMAIN:    case VMGM_DOMAIN:      domain = DVD_READ_MENU_VOBS;      vtsN = 0;      break;    case VTSM_DOMAIN:      domain = DVD_READ_MENU_VOBS;      vtsN = this->position_next.vts;       break;    case VTS_DOMAIN:      domain = DVD_READ_TITLE_VOBS;      vtsN = this->position_next.vts;       break;    default:      printerr("Unknown domain when changing VTS.");      pthread_mutex_unlock(&this->vm_lock);       return DVDNAV_STATUS_ERR;    }        this->position_current.vts = this->position_next.vts;     this->position_current.domain = this->position_next.domain;    dvdnav_read_cache_clear(this->cache);    this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), vtsN, domain);    vts_event->new_vtsN = this->position_next.vts;     vts_event->new_domain = this->position_next.domain;     /* If couldn't open the file for some reason, moan */    if(this->file == NULL) {      printerrf("Error opening vtsN=%i, domain=%i.", vtsN, domain);      pthread_mutex_unlock(&this->vm_lock);       return DVDNAV_STATUS_ERR;    }    /* File opened successfully so return a VTS change event */    (*event) = DVDNAV_VTS_CHANGE;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: VTS_CHANGE\n");#endif    (*len) = sizeof(dvdnav_vts_change_event_t);    this->spu_clut_changed = 1;    this->position_current.cell = -1; /* Force an update */    this->position_current.spu_channel = -1; /* Force an update */    this->position_current.audio_channel = -1; /* Force an update */;         pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  /* Check if the cell changed */    if( (this->position_current.cell != this->position_next.cell) ||      (this->position_current.cell_restart != this->position_next.cell_restart) ||      (this->position_current.cell_start != this->position_next.cell_start) ) {    dvdnav_cell_change_event_t *cell_event = (dvdnav_cell_change_event_t *)*buf;    int32_t first_cell_nr, last_cell_nr, i;    dvd_state_t *state = &this->vm->state;        (*event) = DVDNAV_CELL_CHANGE;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: CELL_CHANGE\n");#endif    (*len) = sizeof(dvdnav_cell_change_event_t);        cell_event->cellN = state->cellN;    cell_event->pgN   = state->pgN;    cell_event->cell_length =      dvdnav_convert_time(&state->pgc->cell_playback[state->cellN-1].playback_time);    cell_event->pg_length = 0;    /* 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;    for (i = first_cell_nr; i <= last_cell_nr; i++)      cell_event->pg_length +=        dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time);    cell_event->pgc_length = dvdnav_convert_time(&state->pgc->playback_time);    cell_event->cell_start = 0;    for (i = 1; i < state->cellN; i++)      cell_event->cell_start +=        dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time);    cell_event->pg_start = 0;    for (i = 1; i < state->pgc->program_map[state->pgN-1]; i++)      cell_event->pg_start +=        dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time);    this->position_current.cell         = this->position_next.cell;    this->position_current.cell_restart = this->position_next.cell_restart;    this->position_current.cell_start   = this->position_next.cell_start;    this->position_current.block        = this->position_next.block;        /* vobu info is used for mid cell resumes */    this->vobu.vobu_start               = this->position_next.cell_start + this->position_next.block;    this->vobu.vobu_next                = 0;    /* Make blockN == vobu_length to do expected_nav */    this->vobu.vobu_length = 0;    this->vobu.blockN      = 0;        /* update the spu palette at least on PGC changes */    this->spu_clut_changed = 1;    this->position_current.spu_channel = -1; /* Force an update */    this->position_current.audio_channel = -1; /* Force an update */    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }   /* has the CLUT changed? */  if(this->spu_clut_changed) {    (*event) = DVDNAV_SPU_CLUT_CHANGE;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n");#endif    (*len) = 16 * sizeof(uint32_t);    memcpy(*buf, &(state->pgc->palette), 16 * sizeof(uint32_t));    this->spu_clut_changed = 0;    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  /* has the SPU channel changed? */    if(this->position_current.spu_channel != this->position_next.spu_channel) {    dvdnav_spu_stream_change_event_t *stream_change = (dvdnav_spu_stream_change_event_t *)*buf;    (*event) = DVDNAV_SPU_STREAM_CHANGE;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE\n");#endif    (*len) = sizeof(dvdnav_spu_stream_change_event_t);    stream_change->physical_wide      = vm_get_subp_active_stream(this->vm, 0);    stream_change->physical_letterbox = vm_get_subp_active_stream(this->vm, 1);    stream_change->physical_pan_scan  = vm_get_subp_active_stream(this->vm, 2);    this->position_current.spu_channel = this->position_next.spu_channel;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_wide=%d\n",stream_change->physical_wide);    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_letterbox=%d\n",stream_change->physical_letterbox);    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_pan_scan=%d\n",stream_change->physical_pan_scan);    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE returning DVDNAV_STATUS_OK\n");#endif    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  /* has the audio channel changed? */    if(this->position_current.audio_channel != this->position_next.audio_channel) {    dvdnav_audio_stream_change_event_t *stream_change = (dvdnav_audio_stream_change_event_t *)*buf;        (*event) = DVDNAV_AUDIO_STREAM_CHANGE;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE\n");#endif    (*len) = sizeof(dvdnav_audio_stream_change_event_t);    stream_change->physical = vm_get_audio_active_stream( this->vm );    this->position_current.audio_channel = this->position_next.audio_channel;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE stream_id=%d returning DVDNAV_STATUS_OK\n",stream_change->physical);#endif    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }       /* Check the STILLFRAME flag */  if(this->position_current.still != 0) {    dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)*buf;    (*event) = DVDNAV_STILL_FRAME;#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: STILL_FRAME\n");#endif    (*len) = sizeof(dvdnav_still_event_t);    still_event->length = this->position_current.still;    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_OK;  }  /* Have we reached the end of a VOBU? */  if (this->vobu.blockN >= this->vobu.vobu_length) {    /* Have we reached the end of a cell? */    if(this->vobu.vobu_next == SRI_END_OF_CELL) {      /* End of Cell from NAV DSI info */#ifdef LOG_DEBUG      fprintf(MSG_OUT, "libdvdnav: Still set to %x\n", this->position_next.still);#endif      this->position_current.still = this->position_next.still;      /* we are about to leave a cell, so a lot of state changes could occur;       * under certain conditions, the application should get in sync with us before this,       * otherwise it might show stills or menus too shortly */      if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) && !this->sync_wait_skip) {        this->sync_wait = 1;      } else {	if( this->position_current.still == 0 || this->skip_still ) {

⌨️ 快捷键说明

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