Mercurial > mplayer.hg
changeset 20746:a40246d0c941
implemented STREAM_CTRL_GET_CURRENT_TIME and STREAM_CTRL_SEEK_TO_TIME (precise seeking)
author | nicodvb |
---|---|
date | Tue, 07 Nov 2006 22:49:56 +0000 |
parents | e9dacb4f9096 |
children | d639a26d9141 |
files | stream/stream_dvd.c stream/stream_dvd.h |
diffstat | 2 files changed, 111 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/stream/stream_dvd.c Tue Nov 07 22:48:14 2006 +0000 +++ b/stream/stream_dvd.c Tue Nov 07 22:49:56 2006 +0000 @@ -517,6 +517,89 @@ return chapter; } +static double dvd_get_current_time(stream_t *stream, int cell) +{ + int i, tm; + dvd_priv_t *d = stream->priv; + + tm=0; + if(!cell) cell=d->cur_cell; + for(i=0; i<d->cur_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 += dvdtimetomsec(&d->dsi_pack.dsi_gi.c_eltm); + + return (double)tm/1000.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, t2=0; + double tm, duration; + off_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-1) / 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 = ((off_t)cell_sector)<<11; + stream_seek(stream, pos); + do { + stream_skip(stream, 2048); + t = dvdtimetomsec(&d->dsi_pack.dsi_gi.c_eltm); + } while(!t); + tm = dvd_get_current_time(stream, 0); + + pos = ((off_t)tmap_sector)<<11; + stream_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) { + if(!stream_skip(stream, 2048)) + break; + tm = dvd_get_current_time(stream, 0); + }; + tmap_sector = stream->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 = ((off_t)vobu_sector) << 11; + stream_seek(stream, pos); + + return 1; +} + static int control(stream_t *stream,int cmd,void* arg) { dvd_priv_t *d = stream->priv; @@ -545,6 +628,23 @@ *((unsigned int *)arg) = dvd_chapter_from_cell(d, d->cur_title-1, d->cur_cell); return 1; } + case STREAM_CTRL_GET_CURRENT_TIME: + { + double tm = dvd_get_current_time(stream, 0); + if(tm != -1) { + tm *= 1000.0f; + *((unsigned int *)arg) = (unsigned int) tm; + return 1; + } + break; + } + case STREAM_CTRL_SEEK_TO_TIME: + { + dvd_priv_t *d = stream->priv; + if(dvd_seek_to_time(stream, d->vts_file, *((double*)arg))) + return 1; + break; + } } return STREAM_UNSUPORTED; } @@ -553,6 +653,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { struct stream_priv_s* p = (struct stream_priv_s*)opts; char *filename; + int k; filename = strdup(stream->url); mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", filename); @@ -857,6 +958,7 @@ */ pgc_id = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgcn; // local pgn = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgn; // local + d->cur_pgc_idx = pgc_id-1; d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc; d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here d->packs_left=-1; // for Navi stuff @@ -874,6 +976,13 @@ d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); + //assign cell_times_table + d->cell_times_table = malloc(sizeof(unsigned int) * d->cur_pgc->nr_of_cells); + if(d->cell_times_table == NULL) + return STREAM_UNSUPORTED; + for(k=0; k<d->cur_pgc->nr_of_cells; k++) + d->cell_times_table[k] = dvdtimetomsec(&d->cur_pgc->cell_playback[k].playback_time); + // ... (unimplemented) // return NULL; stream->type = STREAMTYPE_DVD;
--- a/stream/stream_dvd.h Tue Nov 07 22:48:14 2006 +0000 +++ b/stream/stream_dvd.h Tue Nov 07 22:49:56 2006 +0000 @@ -32,10 +32,12 @@ int last_cell; int cur_pack; int cell_last_pack; + int cur_pgc_idx; // Navi: int packs_left; dsi_t dsi_pack; int angle_seek; + unsigned int *cell_times_table; // audio datas int nr_of_channels; stream_language_t audio_streams[32];