diff options
author | wm4 <wm4@nowhere> | 2014-04-16 21:29:49 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-04-17 01:43:07 +0200 |
commit | 8ed1641c3b976e0cf643e371693831715b749a42 (patch) | |
tree | 0431ed1ee6a6b6cbe25c2af44d2fbb8a712ff65c | |
parent | c5613aa8a20c4d9b58e0ea8f0318f29600c85f5a (diff) |
stream_dvd: fix seeking regression
This was accidentally completely destroyed with commit 24f1878e. I
didn't notice it when testing, because forward seeking still worked
mostly.
The issue was that dvd_seek_to_time() actually called stream_seek(),
which was supposed to call the byte-level seek function dvd_seek(). So
we have to restore this function, and replace all generic stream calls
with stream_dvd.c internal ones. This also affects stream->pos (now a
random number as far as stream_dvd.c is concerned) and stream_skip().
-rw-r--r-- | stream/stream_dvd.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 87d34df91b..c724832c1b 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -461,6 +461,44 @@ static double dvd_get_current_time(stream_t *stream, int cell) return (double)tm/1000.0; } +static void dvd_seek(stream_t *stream, dvd_priv_t *d, int pos) +{ + d->packs_left=-1; + d->cur_pack=pos; + + // check if we stay in current cell (speedup things, and avoid angle skip) + if(d->cur_pack>d->cell_last_pack || + d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector) { + + // ok, cell change, find the right cell! + cell_playback_t *cell; + for(d->cur_cell=0; d->cur_cell < d->cur_pgc->nr_of_cells; d->cur_cell++) { + cell = &(d->cur_pgc->cell_playback[d->cur_cell]); + if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) + continue; + d->cell_last_pack=cell->last_sector; + if(d->cur_pack<cell->first_sector) { + d->cur_pack=cell->first_sector; + break; + } + if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :) + } + } + + MP_VERBOSE(stream, "DVD Seek! lba=0x%X cell=%d packs: 0x%X-0x%X \n", + d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack); + + // if we're in interleaved multi-angle cell, find the right angle chain! + // (read Navi block, and use the seamless angle jump table) + d->angle_seek=1; +} + +static int do_seek(stream_t *s, int64_t newpos) { + stream_drop_buffers(s); + dvd_seek(s, s->priv,newpos/2048); + return 1; +} + 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; @@ -494,23 +532,26 @@ static int dvd_seek_to_time(stream_t *stream, ifo_handle_t *vts_file, double sec } pos = ((int64_t)cell_sector)<<11; - stream_seek(stream, pos); + do_seek(stream, pos); do { - stream_skip(stream, 2048); + char buf[2048]; + dvd_read_sector(stream, stream->priv, buf); // skip 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; - stream_seek(stream, pos); + 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) { - if(!stream_skip(stream, 2048)) - break; + 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 = stream->pos >> 11; + 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 @@ -520,7 +561,7 @@ static int dvd_seek_to_time(stream_t *stream, ifo_handle_t *vts_file, double sec } vobu_sector = vts_file->vts_vobu_admap->vobu_start_sectors[i-1]; pos = ((int64_t)vobu_sector) << 11; - stream_seek(stream, pos); + do_seek(stream, pos); return 1; } @@ -935,7 +976,6 @@ static int open_s(stream_t *stream, int mode) // return NULL; stream->type = STREAMTYPE_DVD; stream->sector_size = 2048; - stream->flags = MP_STREAM_SEEK; stream->fill_buffer = fill_buffer; stream->control = control; stream->close = stream_dvd_close; |