static void list_chapters(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no) { unsigned int i, cell, last_cell; unsigned int t=0, t2=0; ptt_info_t *ptt; pgc_t *pgc; title_no = tt_srpt->title[title_no].vts_ttn - 1; if(vts_file->vts_ptt_srpt->title[title_no].nr_of_ptts < 2) return; ptt = vts_file->vts_ptt_srpt->title[title_no].ptt; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "CHAPTERS: "); for(i=0; i<vts_file->vts_ptt_srpt->title[title_no].nr_of_ptts; i++) { pgc = vts_file->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; cell = pgc->program_map[ptt[i].pgn-1]; //here the cell is 1-based if(ptt[i].pgn<pgc->nr_of_programs) last_cell = pgc->program_map[ptt[i].pgn]; else last_cell = 0; t2 = t/1000; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "%02d:%02d:%02d,", t2/3600, (t2/60)%60, t2%60); do { if(!(pgc->cell_playback[cell-1].block_type == BLOCK_TYPE_ANGLE_BLOCK && pgc->cell_playback[cell-1].block_mode != BLOCK_MODE_FIRST_CELL) ) t += mp_dvdtimetomsec(&pgc->cell_playback[cell-1].playback_time); cell++; } while(cell < last_cell); } mp_msg(MSGT_IDENTIFY, MSGL_INFO, "\n"); }
static double dvd_get_current_time(stream_t *stream, int cell) { int i, tm; dvd_priv_t *d = stream->priv; tm=0; if(cell < 0) cell=d->cur_cell; for(i=0; i<cell; i++) { if(d->cur_pgc->cell_playback[i].block_type == BLOCK_TYPE_ANGLE_BLOCK && d->cur_pgc->cell_playback[i].block_mode != BLOCK_MODE_FIRST_CELL ) continue; tm += d->cell_times_table[i]; } tm += mp_dvdtimetomsec(&d->dsi_pack.dsi_gi.c_eltm); return (double)tm/1000.0; }
static int mp_get_titleset_length(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no) { int vts_ttn; ///< title number within video title set int pgc_no; ///< program chain number int msec; ///< time length in milliseconds msec=0; if(!vts_file || !tt_srpt) return 0; if(vts_file->vtsi_mat && vts_file->vts_pgcit) { vts_ttn = tt_srpt->title[title_no].vts_ttn - 1; pgc_no = vts_file->vts_ptt_srpt->title[vts_ttn].ptt[0].pgcn - 1; msec = mp_dvdtimetomsec(&vts_file->vts_pgcit->pgci_srp[pgc_no].pgc->playback_time); } return msec; }
// p: in=chapter number, out=PTS static int get_chapter_time(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no, double *p) { unsigned int i, cell, last_cell; unsigned int t=0; ptt_info_t *ptt; pgc_t *pgc; title_no = tt_srpt->title[title_no].vts_ttn - 1; if(vts_file->vts_ptt_srpt->title[title_no].nr_of_ptts < 2) return 0; ptt = vts_file->vts_ptt_srpt->title[title_no].ptt; int cur = 0; for(i=0; i<vts_file->vts_ptt_srpt->title[title_no].nr_of_ptts; i++) { pgc = vts_file->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; cell = pgc->program_map[ptt[i].pgn-1]; //here the cell is 1-based if(ptt[i].pgn<pgc->nr_of_programs) last_cell = pgc->program_map[ptt[i].pgn]; else last_cell = 0; while (cell < last_cell) { if(!(pgc->cell_playback[cell-1].block_type == BLOCK_TYPE_ANGLE_BLOCK && pgc->cell_playback[cell-1].block_mode != BLOCK_MODE_FIRST_CELL) ) { if (cur == *p) { *p = t / 1000.0; return 1; } t += mp_dvdtimetomsec(&pgc->cell_playback[cell-1].playback_time); cur++; } cell++; } } return 0; }
static int dvd_seek_to_time(stream_t *stream, ifo_handle_t *vts_file, double sec) { unsigned int i, j, k, timeunit, ac_time, tmap_sector=0, cell_sector=0, vobu_sector=0; int t=0; double tm, duration; int64_t pos = -1; dvd_priv_t *d = stream->priv; vts_tmapt_t *vts_tmapt = vts_file->vts_tmapt; if(!vts_file->vts_tmapt || sec < 0) return 0; duration = (double) mp_get_titleset_length(d->vts_file, d->tt_srpt, d->cur_title) / 1000.0f; if(sec > duration) return 0; i=d->cur_pgc_idx; timeunit = vts_tmapt->tmap[i].tmu; for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) { ac_time = timeunit * (j + 1); if(ac_time >= sec) break; tmap_sector = vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff; } //search enclosing cell for(i=0; i<d->cur_pgc->nr_of_cells; i++) { if(tmap_sector >= d->cur_pgc->cell_playback[i].first_sector && tmap_sector <= d->cur_pgc->cell_playback[i].last_sector) { cell_sector = d->cur_pgc->cell_playback[i].first_sector; break; } } pos = ((int64_t)cell_sector)<<11; do_seek(stream, pos); do { char buf[2048]; if (dvd_read_sector(stream, stream->priv, buf) < 0) // skip break; t = mp_dvdtimetomsec(&d->dsi_pack.dsi_gi.c_eltm); } while(!t); tm = dvd_get_current_time(stream, -1); pos = ((int64_t)tmap_sector)<<11; do_seek(stream, pos); //now get current time in terms of the cell+cell time offset memset(&d->dsi_pack.dsi_gi.c_eltm, 0, sizeof(dvd_time_t)); while(tm <= sec) { char buf[2048]; if (dvd_read_sector(stream, stream->priv, buf) < 0) // skip break; pos += 2048; tm = dvd_get_current_time(stream, -1); }; tmap_sector = pos >> 11; //search closest VOBU sector k=(vts_file->vts_vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE)/4; //entries in the vobu admap for(i=1; i<k; i++) { if(vts_file->vts_vobu_admap->vobu_start_sectors[i] > tmap_sector) break; } vobu_sector = vts_file->vts_vobu_admap->vobu_start_sectors[i-1]; pos = ((int64_t)vobu_sector) << 11; do_seek(stream, pos); return 1; }
static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) { int event = DVDNAV_NOP; *len=-1; if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) { mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(priv->dvdnav) ); *len=-1; } else if (event!=DVDNAV_BLOCK_OK) { // need to handle certain events internally (like skipping stills) switch (event) { case DVDNAV_NAV_PACKET: return event; case DVDNAV_STILL_FRAME: { dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf; priv->still_length = still_event->length; /* set still frame duration */ priv->duration = dvdnav_get_duration (priv->still_length); if (priv->still_length <= 1) { pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); } break; } case DVDNAV_HIGHLIGHT: { dvdnav_get_highlight (priv, 1); break; } case DVDNAV_CELL_CHANGE: { dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t*)buf; uint32_t nextstill; priv->state &= ~NAV_FLAG_WAIT_SKIP; priv->state |= NAV_FLAG_STREAM_CHANGE; if(ev->pgc_length) priv->duration = ev->pgc_length/90; if (dvdnav_is_domain_vts(priv->dvdnav)) { mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MOVIE\n"); priv->state &= ~NAV_FLAG_VTS_DOMAIN; } else { mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MENU\n"); priv->state |= NAV_FLAG_VTS_DOMAIN; } nextstill = dvdnav_get_next_still_flag (priv->dvdnav); if (nextstill) { priv->duration = dvdnav_get_duration (nextstill); priv->still_length = nextstill; if (priv->still_length <= 1) { pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav); priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm); } } break; } case DVDNAV_SPU_CLUT_CHANGE: { memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int)); priv->state |= NAV_FLAG_SPU_SET; break; } case DVDNAV_WAIT: { if ((priv->state & NAV_FLAG_WAIT_SKIP) && !(priv->state & NAV_FLAG_WAIT)) dvdnav_wait_skip (priv->dvdnav); else priv->state |= NAV_FLAG_WAIT; break; } case DVDNAV_VTS_CHANGE: { priv->state &= ~NAV_FLAG_WAIT_SKIP; priv->state |= NAV_FLAG_STREAM_CHANGE; break; } case DVDNAV_SPU_STREAM_CHANGE: { priv->state |= NAV_FLAG_STREAM_CHANGE; break; } } *len=0; } return event; }