From 2d91b19956c7d444ba440078e1c2ecd23d207a87 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 2 Apr 2009 05:00:22 +0300 Subject: [PATCH] Support chapter seeking with ordered chapters --- command.c | 8 ++++---- libmpdemux/demux_mkv.c | 1 + libmpdemux/demuxer.h | 1 + mp_core.h | 13 +++++++++++- mplayer.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/command.c b/command.c index 97fc66ba7c..2a51b244c7 100644 --- a/command.c +++ b/command.c @@ -5,6 +5,7 @@ #include #include "config.h" +#include "talloc.h" #include "command.h" #include "input/input.h" #include "stream/stream.h" @@ -391,7 +392,7 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, char *chapter_name = NULL; if (mpctx->demuxer) - chapter = demuxer_get_current_chapter(mpctx->demuxer); + chapter = get_current_chapter(mpctx); if (chapter < 0) return M_PROPERTY_UNAVAILABLE; @@ -404,7 +405,7 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, case M_PROPERTY_PRINT: { if (!arg) return M_PROPERTY_ERROR; - chapter_name = demuxer_chapter_display_name(mpctx->demuxer, chapter); + chapter_name = chapter_display_name(mpctx, chapter); if (!chapter_name) return M_PROPERTY_UNAVAILABLE; *(char **) arg = chapter_name; @@ -431,8 +432,7 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, } double next_pts = 0; - chapter = demuxer_seek_chapter(mpctx->demuxer, chapter, &next_pts, - &chapter_name); + chapter = seek_chapter(mpctx, chapter, &next_pts, &chapter_name); mpctx->rel_seek_secs = 0; mpctx->abs_seek_pos = 0; if (chapter >= 0) { diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index f98a2d0645..e9853bc3e4 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -1170,6 +1170,7 @@ static uint64_t read_one_chapter(struct demuxer *demuxer, stream_t *s) m->num_ordered_chapters + 1); chapter.start = start; chapter.end = end; + chapter.name = talloc_strdup(m->ordered_chapters, name); // Will be undone later if this is a normal chapter rather than ordered m->ordered_chapters[m->num_ordered_chapters] = chapter; m->num_ordered_chapters++; diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 6df2564e24..544afe8add 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -198,6 +198,7 @@ struct matroska_data { uint64_t end; bool has_segment_uid; unsigned char segment_uid[16]; + char *name; } *ordered_chapters; int num_ordered_chapters; }; diff --git a/mp_core.h b/mp_core.h index 6b7719b7f3..67b3c6c922 100644 --- a/mp_core.h +++ b/mp_core.h @@ -58,6 +58,11 @@ struct timeline_part { struct content_source *source; }; +struct chapter { + double start; + char *name; +}; + typedef struct MPContext { struct MPOpts opts; struct m_config *mconfig; @@ -85,6 +90,8 @@ typedef struct MPContext { struct timeline_part *timeline; int num_timeline_parts; int timeline_part; + struct chapter *chapters; + int num_chapters; double video_offset; struct stream *stream; @@ -130,7 +137,7 @@ typedef struct MPContext { unsigned int last_time; // Used to communicate the parameters of a seek between parts - float rel_seek_secs; + double rel_seek_secs; int abs_seek_pos; float begin_skip; ///< start time of the current skip while on edlout mode @@ -188,5 +195,9 @@ int reinit_video_chain(struct MPContext *mpctx); void pause_player(struct MPContext *mpctx); void unpause_player(struct MPContext *mpctx); void add_step_frame(struct MPContext *mpctx); +int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts, + char **chapter_name); +int get_current_chapter(struct MPContext *mpctx); +char *chapter_display_name(struct MPContext *mpctx, int chapter); #endif /* MPLAYER_MP_CORE_H */ diff --git a/mplayer.c b/mplayer.c index 42d24f03e6..bd5957cee0 100644 --- a/mplayer.c +++ b/mplayer.c @@ -579,6 +579,8 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask){ talloc_free(mpctx->timeline); mpctx->timeline = NULL; mpctx->num_timeline_parts = 0; + talloc_free(mpctx->chapters); + mpctx->num_chapters = 0; mpctx->video_offset = 0; if(mpctx->demuxer){ mpctx->stream=mpctx->demuxer->stream; @@ -2618,6 +2620,43 @@ static int seek(MPContext *mpctx, double amount, int style) return 0; } +int get_current_chapter(struct MPContext *mpctx) +{ + if (!mpctx->chapters || !mpctx->sh_video) + return demuxer_get_current_chapter(mpctx->demuxer); + + int i; + double current_pts = mpctx->sh_video->pts; + for (i = 1; i < mpctx->num_chapters; i++) + if (current_pts < mpctx->chapters[i].start) + break; + return i - 1; +} + +// currently returns a string allocated with malloc, not talloc +char *chapter_display_name(struct MPContext *mpctx, int chapter) +{ + if (!mpctx->chapters || !mpctx->sh_video) + return demuxer_chapter_display_name(mpctx->demuxer, chapter); + return strdup(mpctx->chapters[chapter].name); +} + +int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts, + char **chapter_name) +{ + if (!mpctx->chapters || !mpctx->sh_video) + return demuxer_seek_chapter(mpctx->demuxer, chapter, seek_pts, + chapter_name); + if (chapter >= mpctx->num_chapters) + return -1; + if (chapter < 0) + chapter = 0; + *seek_pts = mpctx->chapters[chapter].start; + if (chapter_name) + *chapter_name = talloc_strdup(NULL, mpctx->chapters[chapter].name); + return chapter; +} + static int find_ordered_chapter_sources(struct MPContext *mpctx, struct content_source *sources, int num_sources, @@ -2726,9 +2765,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) struct timeline_part *timeline = talloc_array_ptrtype(NULL, timeline, m->num_ordered_chapters + 1); + struct chapter *chapters = talloc_array_ptrtype(NULL, chapters, + m->num_ordered_chapters); uint64_t starttime = 0; uint64_t missing_time = 0; int part_count = 0; + int num_chapters = 0; for (int i = 0; i < m->num_ordered_chapters; i++) { struct matroska_chapter *c = m->ordered_chapters + i; @@ -2740,6 +2782,8 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) missing_time += c->end - c->start; continue; found2:; + chapters[num_chapters].start = starttime / 1000.; + chapters[num_chapters].name = talloc_strdup(chapters, c->name); // Only add a separate part if the time or file actually changes uint64_t prev_end = !part_count ? 0 : starttime - timeline[part_count - 1].start @@ -2747,11 +2791,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) if (part_count == 0 || c->start != prev_end || sources + j != timeline[part_count - 1].source) { timeline[part_count].source = sources + j; - timeline[part_count].start = starttime / 1000.; + timeline[part_count].start = chapters[num_chapters].start; timeline[part_count].source_start = c->start / 1000.; part_count++; } starttime += c->end - c->start; + num_chapters++; } timeline[part_count].start = starttime / 1000.; @@ -2759,6 +2804,7 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) // None of the parts come from the file itself??? talloc_free(sources); talloc_free(timeline); + talloc_free(chapters); return; } @@ -2784,6 +2830,9 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) mpctx->num_sources = num_sources; mpctx->timeline = timeline; mpctx->num_timeline_parts = part_count; + mpctx->num_chapters = num_chapters; + mpctx->chapters = chapters; + mpctx->timeline_part = 0; mpctx->video_offset = timeline[0].source_start; mpctx->demuxer = timeline[0].source->demuxer; @@ -3593,7 +3642,7 @@ if(!mpctx->demuxer) if(dvd_chapter>1) { double pts; - if (demuxer_seek_chapter(mpctx->demuxer, dvd_chapter-1, &pts, NULL) >= 0 && pts > -1.0) + if (seek_chapter(mpctx, dvd_chapter-1, &pts, NULL) >= 0 && pts > -1.0) seek(mpctx, pts, SEEK_ABSOLUTE); } @@ -3993,7 +4042,7 @@ while(!mpctx->stop_play){ float aq_sleep_time=0; if(dvd_last_chapter>0) { - int cur_chapter = demuxer_get_current_chapter(mpctx->demuxer); + int cur_chapter = get_current_chapter(mpctx); if(cur_chapter!=-1 && cur_chapter+1>dvd_last_chapter) goto goto_next_file; } -- 2.11.4.GIT