mirror of
https://github.com/mpv-player/mpv
synced 2024-12-26 00:42:57 +00:00
Support chapter seeking with ordered chapters
This commit is contained in:
parent
f12c83b85b
commit
2d91b19956
@ -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) {
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
};
|
||||
|
13
mp_core.h
13
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 */
|
||||
|
55
mplayer.c
55
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user