summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-04-02 05:00:22 +0300
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-04-02 06:51:26 +0300
commit2d91b19956c7d444ba440078e1c2ecd23d207a87 (patch)
tree27e0cac3e0f6ab3286ab6ec221ab763605113734
parentf12c83b85b135c1cb9fb34e978eb0c8051450da8 (diff)
downloadmpv-2d91b19956c7d444ba440078e1c2ecd23d207a87.tar.bz2
mpv-2d91b19956c7d444ba440078e1c2ecd23d207a87.tar.xz
Support chapter seeking with ordered chapters
-rw-r--r--command.c8
-rw-r--r--libmpdemux/demux_mkv.c1
-rw-r--r--libmpdemux/demuxer.h1
-rw-r--r--mp_core.h13
-rw-r--r--mplayer.c55
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 <stdbool.h>
#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;
}