summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-02-17 23:46:12 +0100
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2015-02-19 13:39:38 +0900
commit630a7b7d82d48b9561940a08d5291495dc2b1079 (patch)
treefcae6410c0b8a9cfb6c3f8f0fdb5a7e1fec8d06e
parenta4e766a77fc6b7d3ac2e9cfdbbf28b5e042f90b9 (diff)
downloadmpv-630a7b7d82d48b9561940a08d5291495dc2b1079.tar.bz2
mpv-630a7b7d82d48b9561940a08d5291495dc2b1079.tar.xz
player: use a separate context for timeline loader stuff
Instead of accessing MPContext in player/timeline/*, create a separate context struct, which the timeline loaders fill out. It turns out that there's not much in the way too big MPContext that these need to access. One major PITA is managing (and closing) the set of open demuxers. The problem is that we need a list of all demuxers to make sure no unneeded streams are enabled. This adds a callback to the demuxer_desc struct, with the intention of leaving to to the demuxer to call the right loader, instead of explicitly checking the demuxer type and dispatching manually in common code. I also considered making the timeline part of the demuxer state, but decided against: it's too much of a mess wrt. memory management and threading, and also doesn't make it clear who owns the child demuxers. With the struct timeline decoupled from the demuxer state, it's at least somewhat clear that the child demuxers are independent from the "main" demuxer. The actual changes to player/timeline/* are separated in the following commits, because they're quite verbose. Some artifacts will be removed later as soon as there's only 1 timeline loading mechanism. (cherry picked from commit a0a089f6a48c2775478b544185a0ddeabf43cce8)
-rw-r--r--demux/demux.h3
-rw-r--r--demux/timeline.c42
-rw-r--r--demux/timeline.h37
-rw-r--r--old-makefile1
-rw-r--r--player/core.h8
-rw-r--r--player/loadfile.c60
-rw-r--r--wscript_build.py1
7 files changed, 130 insertions, 22 deletions
diff --git a/demux/demux.h b/demux/demux.h
index e18c013a5b..708bce31bc 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -104,6 +104,7 @@ enum demux_event {
#define MAX_SH_STREAMS 256
struct demuxer;
+struct timeline;
/**
* Demuxer description structure
@@ -121,6 +122,8 @@ typedef struct demuxer_desc {
void (*close)(struct demuxer *demuxer);
void (*seek)(struct demuxer *demuxer, double rel_seek_secs, int flags);
int (*control)(struct demuxer *demuxer, int cmd, void *arg);
+ // See timeline.c
+ void (*load_timeline)(struct timeline *tl);
} demuxer_desc_t;
typedef struct demux_chapter
diff --git a/demux/timeline.c b/demux/timeline.c
new file mode 100644
index 0000000000..6274c25fa3
--- /dev/null
+++ b/demux/timeline.c
@@ -0,0 +1,42 @@
+#include "common/common.h"
+#include "stream/stream.h"
+#include "demux.h"
+
+#include "timeline.h"
+
+struct timeline *timeline_load(struct mpv_global *global, struct mp_log *log,
+ struct demuxer *demuxer)
+{
+ if (!demuxer->desc->load_timeline)
+ return NULL;
+
+ struct timeline *tl = talloc_ptrtype(NULL, tl);
+ *tl = (struct timeline){
+ .global = global,
+ .log = log,
+ .demuxer = demuxer,
+ .track_layout = demuxer,
+ };
+
+ demuxer->desc->load_timeline(tl);
+
+ if (tl->num_parts)
+ return tl;
+ timeline_destroy(tl);
+ return NULL;
+}
+
+void timeline_destroy(struct timeline *tl)
+{
+ if (!tl)
+ return;
+ for (int n = 0; n < tl->num_sources; n++) {
+ struct demuxer *d = tl->sources[n];
+ if (d != tl->demuxer) {
+ struct stream *s = d->stream;
+ free_demuxer(d);
+ free_stream(s);
+ }
+ }
+ talloc_free(tl);
+}
diff --git a/demux/timeline.h b/demux/timeline.h
new file mode 100644
index 0000000000..e4d6f67953
--- /dev/null
+++ b/demux/timeline.h
@@ -0,0 +1,37 @@
+#ifndef MP_TIMELINE_H_
+#define MP_TIMELINE_H_
+
+struct timeline_part {
+ double start;
+ double source_start;
+ struct demuxer *source;
+};
+
+struct timeline {
+ struct mpv_global *global;
+ struct mp_log *log;
+
+ // main source
+ struct demuxer *demuxer;
+
+ // All referenced files. The source file must be at sources[0].
+ struct demuxer **sources;
+ int num_sources;
+
+ // Segments to play, ordered by time. parts[num_parts] must be valid; its
+ // start field sets the duration, and source must be NULL.
+ struct timeline_part *parts;
+ int num_parts;
+
+ struct demux_chapter *chapters;
+ int num_chapters;
+
+ // Which source defines the overall track list (over the full timeline).
+ struct demuxer *track_layout;
+};
+
+struct timeline *timeline_load(struct mpv_global *global, struct mp_log *log,
+ struct demuxer *demuxer);
+void timeline_destroy(struct timeline *tl);
+
+#endif
diff --git a/old-makefile b/old-makefile
index f489383691..944a7a8435 100644
--- a/old-makefile
+++ b/old-makefile
@@ -176,6 +176,7 @@ SOURCES = audio/audio.c \
demux/demux_subreader.c \
demux/ebml.c \
demux/packet.c \
+ demux/timeline.c \
input/cmd_list.c \
input/cmd_parse.c \
input/event.c \
diff --git a/player/core.h b/player/core.h
index d6475eb385..6cb77f7499 100644
--- a/player/core.h
+++ b/player/core.h
@@ -26,6 +26,7 @@
#include "common/common.h"
#include "options/options.h"
#include "sub/osd.h"
+#include "demux/timeline.h"
// definitions used internally by the core player code
@@ -41,12 +42,6 @@ enum stop_play_reason {
PT_ERROR, // play next playlist entry (due to an error)
};
-struct timeline_part {
- double start;
- double source_start;
- struct demuxer *source;
-};
-
enum mp_osd_seek_info {
OSD_SEEK_INFO_BAR = 1,
OSD_SEEK_INFO_TEXT = 2,
@@ -188,6 +183,7 @@ typedef struct MPContext {
struct demuxer **sources;
int num_sources;
+ struct timeline *tl;
struct timeline_part *timeline;
int num_timeline_parts;
int timeline_part;
diff --git a/player/loadfile.c b/player/loadfile.c
index 27ab3a15b0..98e32adaf2 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -100,12 +100,19 @@ static void uninit_demuxer(struct MPContext *mpctx)
mpctx->track_layout = NULL;
mpctx->master_demuxer = NULL;
mpctx->demuxer = NULL;
- talloc_free(mpctx->timeline);
- mpctx->timeline = NULL;
- mpctx->num_timeline_parts = 0;
+ if (!mpctx->tl)
+ mpctx->num_timeline_parts = 0;
for (int i = 0; i < mpctx->num_sources; i++)
uninit_stream_sub_decoders(mpctx->sources[i]);
close_unused_demuxers(mpctx);
+ if (mpctx->tl) {
+ timeline_destroy(mpctx->tl);
+ } else {
+ talloc_free(mpctx->timeline);
+ }
+ mpctx->timeline = NULL;
+ mpctx->num_timeline_parts = 0;
+ mpctx->tl = NULL;
if (mpctx->num_sources > 0)
free_demuxer(mpctx->sources[0]);
talloc_free(mpctx->sources);
@@ -971,6 +978,39 @@ static struct demuxer *open_demux_async(struct MPContext *mpctx,
return args.demux;
}
+static void load_timeline(struct MPContext *mpctx)
+{
+ mpctx->track_layout = mpctx->demuxer;
+
+ MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, mpctx->demuxer);
+
+ if (mpctx->demuxer->matroska_data.ordered_chapters)
+ build_ordered_chapter_timeline(mpctx);
+
+ if (mpctx->demuxer->type == DEMUXER_TYPE_EDL)
+ build_mpv_edl_timeline(mpctx);
+
+ if (mpctx->demuxer->type == DEMUXER_TYPE_CUE)
+ build_cue_timeline(mpctx);
+
+ mpctx->tl = timeline_load(mpctx->global, mpctx->log, mpctx->demuxer);
+ if (mpctx->tl) {
+ mpctx->timeline = mpctx->tl->parts;
+ mpctx->num_timeline_parts = mpctx->tl->num_parts;
+ mpctx->num_chapters = mpctx->tl->num_chapters;
+ mpctx->chapters = demux_copy_chapter_data(mpctx->tl->chapters,
+ mpctx->tl->num_chapters);
+ mpctx->track_layout = mpctx->tl->track_layout;
+ mpctx->num_sources = 0;
+ for (int n = 0; n < mpctx->tl->num_sources; n++) {
+ MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources,
+ mpctx->tl->sources[n]);
+ }
+ }
+
+ print_timeline(mpctx);
+}
+
// Start playing the current playlist entry.
// Handle initialization and deinitialization.
static void play_current_file(struct MPContext *mpctx)
@@ -1084,7 +1124,7 @@ goto_reopen_demuxer: ;
}
mpctx->master_demuxer = mpctx->demuxer;
- MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, mpctx->demuxer);
+ load_timeline(mpctx);
if (mpctx->demuxer->playlist) {
int entry_stream_flags =
@@ -1099,18 +1139,6 @@ goto_reopen_demuxer: ;
goto terminate_playback;
}
- mpctx->track_layout = mpctx->demuxer;
-
- if (mpctx->demuxer->matroska_data.ordered_chapters)
- build_ordered_chapter_timeline(mpctx);
-
- if (mpctx->demuxer->type == DEMUXER_TYPE_EDL)
- build_mpv_edl_timeline(mpctx);
-
- if (mpctx->demuxer->type == DEMUXER_TYPE_CUE)
- build_cue_timeline(mpctx);
-
- print_timeline(mpctx);
load_chapters(mpctx);
add_demuxer_tracks(mpctx, mpctx->track_layout);
diff --git a/wscript_build.py b/wscript_build.py
index f0f3be9aa5..0b7a4b202a 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -178,6 +178,7 @@ def build(ctx):
( "demux/demux_tv.c", "tv" ),
( "demux/ebml.c" ),
( "demux/packet.c" ),
+ ( "demux/timeline.c" ),
## Input
( "input/cmd_list.c" ),