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; ivts_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;