diff options
author | 2013-05-04 01:20:39 +0200 | |
---|---|---|
committer | 2013-05-06 23:39:48 +0200 | |
commit | b01e8d6210adcf0b68313d1b31f904c121020401 (patch) | |
tree | ca966f78e23f8e2f6e2dc502ba05181b16baeebe | |
parent | 5148f9f5cca6a5a28bb98a3b713f27614538815f (diff) |
stream: report chapter times, use time seeks for DVD chapters
Allow the stream layer to report chapter times. Extend stream_dvd to do
this. I'm not 100% sure whether the re-used code is bug-free (because it
was used for slave-mode and/or debugging only).
MAke the frontend do time-based seeks when switching DVD chapters. I'm
not sure if there's a real reason STREAM_CTRL_SEEK_TO_CHAPTER exists
(maybe/hopefully not), but we will see.
Note that querying chapter times in demuxer_chapter_time() with the new
STREAM_CTRL_GET_CHAPTER_TIME could be excessively slow, especially with
the cache enabled. The frontend likes to query chapter times very often.
Additionally, stream_dvd uses some sort of quadratic algorithm to list
times for all chapters. For this reason, we try to query all chapters on
start (after the demuxer is opened), and add the chapters to the demuxer
chapter list. demuxer_chapter_time() will get the time from that list,
instead of asking the stream layer over and over again.
This assumes stream_dvd knows the list of chapters at the start, and
also that the list of chapters never changes during playback. This
seems to be true, and the only exception, switching DVD titles, is not
supported at runtime (and doesn't need to be supported).
-rw-r--r-- | demux/demux.c | 17 | ||||
-rw-r--r-- | stream/cache2.c | 8 | ||||
-rw-r--r-- | stream/stream.h | 1 | ||||
-rw-r--r-- | stream/stream_dvd.c | 38 |
4 files changed, 58 insertions, 6 deletions
diff --git a/demux/demux.c b/demux/demux.c index 94f54fcbfd..f95a134903 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -101,6 +101,8 @@ const demuxer_desc_t *const demuxer_list[] = { NULL }; +static void add_stream_chapters(struct demuxer *demuxer); + static int packet_destroy(void *ptr) { struct demux_packet *dp = ptr; @@ -932,6 +934,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts, // Doesn't work, because stream_pts is a "guess". demuxer->accurate_seek = false; } + add_stream_chapters(demuxer); demuxer_sort_chapters(demuxer); return demuxer; } else { @@ -1300,6 +1303,20 @@ int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name, return 0; } +static void add_stream_chapters(struct demuxer *demuxer) +{ + if (demuxer->num_chapters) + return; + int num_chapters = demuxer_chapter_count(demuxer); + for (int n = 0; n < num_chapters; n++) { + double p = n; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_CHAPTER_TIME, &p) + != STREAM_OK) + return; + demuxer_add_chapter(demuxer, bstr0(""), p * 1e9, 0); + } +} + /** * \brief demuxer_seek_chapter() seeks to a chapter in two possible ways: * either using the demuxer->chapters structure set by the demuxer diff --git a/stream/cache2.c b/stream/cache2.c index 0c1c70a577..38c57d0af9 100644 --- a/stream/cache2.c +++ b/stream/cache2.c @@ -302,10 +302,11 @@ static int cache_execute_control(cache_vars_t *s) { switch (s->control) { case STREAM_CTRL_SEEK_TO_TIME: needs_flush = 1; - double_res = s->control_double_arg; case STREAM_CTRL_GET_CURRENT_TIME: case STREAM_CTRL_GET_ASPECT_RATIO: case STREAM_CTRL_GET_START_TIME: + case STREAM_CTRL_GET_CHAPTER_TIME: + double_res = s->control_double_arg; s->control_res = s->stream->control(s->stream, s->control, &double_res); s->control_double_arg = double_res; break; @@ -661,6 +662,10 @@ int cache_do_control(stream_t *stream, int cmd, void *arg) { case STREAM_CTRL_GET_START_TIME: *(double *)arg = s->stream_start_time; return s->stream_start_time != MP_NOPTS_VALUE ? STREAM_OK : STREAM_UNSUPPORTED; + case STREAM_CTRL_GET_CHAPTER_TIME: + s->control_double_arg = *(double *)arg; + s->control = cmd; + break; case STREAM_CTRL_GET_LANG: s->control_lang_arg = *(struct stream_lang_req *)arg; case STREAM_CTRL_GET_NUM_TITLES: @@ -705,6 +710,7 @@ int cache_do_control(stream_t *stream, int cmd, void *arg) { case STREAM_CTRL_GET_CURRENT_TIME: case STREAM_CTRL_GET_ASPECT_RATIO: case STREAM_CTRL_GET_START_TIME: + case STREAM_CTRL_GET_CHAPTER_TIME: *(double *)arg = s->control_double_arg; break; case STREAM_CTRL_GET_NUM_TITLES: diff --git a/stream/stream.h b/stream/stream.h index 2d4fd3862d..df4188ed94 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -104,6 +104,7 @@ // DVD/Bluray, signal general support for GET_CURRENT_TIME etc. #define STREAM_CTRL_MANAGES_TIMELINE 19 #define STREAM_CTRL_GET_START_TIME 20 +#define STREAM_CTRL_GET_CHAPTER_TIME 21 struct stream_lang_req { int type; // STREAM_AUDIO, STREAM_SUB diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 5df9b390e7..dc2cdfd2ae 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -498,7 +498,8 @@ static int seek_to_chapter(stream_t *stream, ifo_handle_t *vts_file, tt_srpt_t * return chapter; } -static void list_chapters(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no) +// 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; @@ -507,10 +508,10 @@ static void list_chapters(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_ title_no = tt_srpt->title[title_no].vts_ttn - 1; if(vts_file->vts_ptt_srpt->title[title_no].nr_of_ptts < 2) - return; + return 0; ptt = vts_file->vts_ptt_srpt->title[title_no].ptt; - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "CHAPTERS: "); + 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; @@ -519,15 +520,35 @@ static void list_chapters(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_ last_cell = pgc->program_map[ptt[i].pgn]; else last_cell = 0; - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "%02d:%02d:%02d.%03d,", t/3600000, (t/60000)%60, (t/1000)%60, t%1000); do { 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++; } while(cell < last_cell); } + return 0; +} + +static void list_chapters(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no) +{ + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "CHAPTERS: "); + for (int n = 0; ; n++) { + double p = n; + int r; + r = get_chapter_time(vts_file, tt_srpt, title_no, &p); + if (!r) + break; + int t = p * 1000; + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "%02d:%02d:%02d.%03d,", t/3600000, (t/60000)%60, (t/1000)%60, t%1000); + } mp_msg(MSGT_IDENTIFY, MSGL_INFO, "\n"); } @@ -642,6 +663,13 @@ static int control(stream_t *stream,int cmd,void* arg) *((unsigned int *)arg) = r; return 1; } + case STREAM_CTRL_GET_CHAPTER_TIME: + { + int r; + r = get_chapter_time(d->vts_file, d->tt_srpt, d->cur_title-1, (double *)arg); + if(! r) return STREAM_UNSUPPORTED; + return 1; + } case STREAM_CTRL_SEEK_TO_CHAPTER: { int r; |