summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/edl-mpv.rst16
-rw-r--r--demux/demux_edl.c32
-rw-r--r--demux/demux_timeline.c26
-rw-r--r--demux/timeline.h8
4 files changed, 65 insertions, 17 deletions
diff --git a/DOCS/edl-mpv.rst b/DOCS/edl-mpv.rst
index ec60d09ccc..ac85f427d0 100644
--- a/DOCS/edl-mpv.rst
+++ b/DOCS/edl-mpv.rst
@@ -214,6 +214,16 @@ It provides following parameters change track metadata:
``byterate``
Number of bytes per second this stream uses. (Purely informational.)
+``index``
+ The numeric index of the track this should map to (default: -1). This is
+ the 0-based index of the virtual stream as seen by the player, enumerating
+ all audio/video/subtitle streams. If nothing matches, this is silently
+ discarded. The special index -1 (the default) has two meanings: if there
+ was a previous meta data entry (either ``!track_meta`` or ``!delay_open``
+ element since the last ``!new_stream``), then this element manipulates
+ the previous meta data entry. If there was no previous entry, a new meta
+ data entry that matches all streams is created.
+
Example::
# mpv EDL v0
@@ -244,6 +254,12 @@ Using multiple segments requires you to specify all offsets and durations (also
it was never tested whether it works at all). Interaction with ``mp4_dash`` may
be strange.
+You can describe multiple sub-tracks by using multiple ``delay_open`` headers
+before the same source URL. (If there are multiple sub-tracks of the same media
+type, then the mapping to the real stream is probably rather arbitrary.) If the
+source contains tracks not described, a warning is logged when the delayed
+opening happens, and the track is hidden.
+
This has the following parameters:
``media_type``
diff --git a/demux/demux_edl.c b/demux/demux_edl.c
index e71c1dfd99..f72aeb2c03 100644
--- a/demux/demux_edl.c
+++ b/demux/demux_edl.c
@@ -50,7 +50,8 @@ struct tl_parts {
bool disable_chapters;
bool dash, no_clip, delay_open;
char *init_fragment_url;
- struct sh_stream *sh_meta;
+ struct sh_stream **sh_meta;
+ int num_sh_meta;
struct tl_part *parts;
int num_parts;
struct tl_parts *next;
@@ -145,12 +146,22 @@ static bool get_param_time(struct parse_ctx *ctx, const char *name, double *t)
static struct tl_parts *add_part(struct tl_root *root)
{
struct tl_parts *tl = talloc_zero(root, struct tl_parts);
- tl->sh_meta = demux_alloc_sh_stream(STREAM_TYPE_COUNT);
- talloc_steal(tl, tl->sh_meta);
MP_TARRAY_APPEND(root, root->pars, root->num_pars, tl);
return tl;
}
+static struct sh_stream *get_meta(struct tl_parts *tl, int index)
+{
+ for (int n = 0; n < tl->num_sh_meta; n++) {
+ if (tl->sh_meta[n]->index == index)
+ return tl->sh_meta[n];
+ }
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_TYPE_COUNT);
+ talloc_steal(tl, sh);
+ MP_TARRAY_APPEND(tl, tl->sh_meta, tl->num_sh_meta, sh);
+ return sh;
+}
+
/* Returns a list of parts, or NULL on parse error.
* Syntax (without file header or URI prefix):
* url ::= <entry> ( (';' | '\n') <entry> )*
@@ -223,12 +234,15 @@ static struct tl_root *parse_edl(bstr str, struct mp_log *log)
} else if (bstr_equals0(f_type, "no_chapters")) {
tl->disable_chapters = true;
} else if (bstr_equals0(f_type, "track_meta")) {
- struct sh_stream *sh = tl->sh_meta;
+ int index = get_param_int(&ctx, "index", -1);
+ struct sh_stream *sh = index < 0 && tl->num_sh_meta
+ ? tl->sh_meta[tl->num_sh_meta - 1]
+ : get_meta(tl, index);
sh->lang = get_param0(&ctx, sh, "lang");
sh->title = get_param0(&ctx, sh, "title");
sh->hls_bitrate = get_param_int(&ctx, "byterate", 0) * 8;
} else if (bstr_equals0(f_type, "delay_open")) {
- struct sh_stream *sh = tl->sh_meta;
+ struct sh_stream *sh = get_meta(tl, tl->num_sh_meta);
bstr mt = get_param(&ctx, "media_type");
if (bstr_equals0(mt, "video")) {
sh->type = sh->codec->type = STREAM_VIDEO;
@@ -371,8 +385,12 @@ static struct timeline_par *build_timeline(struct timeline *root,
tl->delay_open = parts->delay_open;
// There is no copy function for sh_stream, so just steal it.
- tl->sh_meta = talloc_steal(tl, parts->sh_meta);
- parts->sh_meta = NULL;
+ for (int n = 0; n < parts->num_sh_meta; n++) {
+ MP_TARRAY_APPEND(tl, tl->sh_meta, tl->num_sh_meta,
+ talloc_steal(tl, parts->sh_meta[n]));
+ parts->sh_meta[n] = NULL;
+ }
+ parts->num_sh_meta = 0;
if (parts->init_fragment_url && parts->init_fragment_url[0]) {
MP_VERBOSE(root, "Opening init fragment...\n");
diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c
index ab6d29b538..eb923d92e4 100644
--- a/demux/demux_timeline.c
+++ b/demux/demux_timeline.c
@@ -528,6 +528,17 @@ static void apply_meta(struct sh_stream *dst, struct sh_stream *src)
dst->attached_picture = src->attached_picture;
}
+// This is mostly for EDL user-defined metadata.
+static struct sh_stream *find_matching_meta(struct timeline_par *tl, int index)
+{
+ for (int n = 0; n < tl->num_sh_meta; n++) {
+ struct sh_stream *sh = tl->sh_meta[n];
+ if (sh->index == index || sh->index < 0)
+ return sh;
+ }
+ return NULL;
+}
+
static bool add_tl(struct demuxer *demuxer, struct timeline_par *tl)
{
struct priv *p = demuxer->priv;
@@ -553,7 +564,7 @@ static bool add_tl(struct demuxer *demuxer, struct timeline_par *tl)
// delay_open streams normally have meta==NULL, and 1 virtual stream
int num_streams = 0;
if (tl->delay_open) {
- num_streams = 1;
+ num_streams = tl->num_sh_meta;
} else if (meta) {
num_streams = demux_get_num_stream(meta);
}
@@ -561,9 +572,10 @@ static bool add_tl(struct demuxer *demuxer, struct timeline_par *tl)
struct sh_stream *new = NULL;
if (tl->delay_open) {
- assert(tl->sh_meta);
- new = demux_alloc_sh_stream(tl->sh_meta->type);
- new->codec = tl->sh_meta->codec;
+ struct sh_stream *tsh = tl->sh_meta[n];
+ new = demux_alloc_sh_stream(tsh->type);
+ new->codec = tsh->codec;
+ apply_meta(new, tsh);
demuxer->is_network = true;
demuxer->is_streaming = true;
} else {
@@ -571,11 +583,11 @@ static bool add_tl(struct demuxer *demuxer, struct timeline_par *tl)
new = demux_alloc_sh_stream(sh->type);
apply_meta(new, sh);
new->codec = sh->codec;
+ struct sh_stream *tsh = find_matching_meta(tl, n);
+ if (tsh)
+ apply_meta(new, tsh);
}
- if (tl->sh_meta)
- apply_meta(new, tl->sh_meta);
-
demux_add_sh_stream(demuxer, new);
struct virtual_stream *vs = talloc_ptrtype(p, vs);
*vs = (struct virtual_stream){
diff --git a/demux/timeline.h b/demux/timeline.h
index faeec53b32..93919a5c51 100644
--- a/demux/timeline.h
+++ b/demux/timeline.h
@@ -24,9 +24,11 @@ struct timeline_par {
bstr init_fragment;
bool dash, no_clip, delay_open;
- // If non-NULL, _some_ fields are used. If delay_open==true, this must be
- // set, and the codec info is used.
- struct sh_stream *sh_meta;
+ // Of any of these, _some_ fields are used. If delay_open==true, this
+ // describes each sub-track, and the codec info is used.
+ // In both cases, the metadata is mapped to actual tracks in specific ways.
+ struct sh_stream **sh_meta;
+ int num_sh_meta;
// Segments to play, ordered by time.
struct timeline_part *parts;