summaryrefslogtreecommitdiffstats
path: root/demux/demux_edl.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/demux_edl.c')
-rw-r--r--demux/demux_edl.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/demux/demux_edl.c b/demux/demux_edl.c
index e71c1dfd99..356b7eefb5 100644
--- a/demux/demux_edl.c
+++ b/demux/demux_edl.c
@@ -32,6 +32,7 @@
#include "options/path.h"
#include "misc/bstr.h"
#include "common/common.h"
+#include "common/tags.h"
#include "stream/stream.h"
#define HEADER "# mpv EDL v0\n"
@@ -50,7 +51,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;
@@ -59,6 +61,7 @@ struct tl_parts {
struct tl_root {
struct tl_parts **pars;
int num_pars;
+ struct mp_tags *tags;
};
struct priv {
@@ -145,12 +148,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> )*
@@ -160,6 +173,7 @@ static struct tl_parts *add_part(struct tl_root *root)
static struct tl_root *parse_edl(bstr str, struct mp_log *log)
{
struct tl_root *root = talloc_zero(NULL, struct tl_root);
+ root->tags = talloc_zero(root, struct mp_tags);
struct tl_parts *tl = add_part(root);
while (str.len) {
if (bstr_eatstart0(&str, "#")) {
@@ -223,12 +237,26 @@ 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;
+ bstr flags = get_param(&ctx, "flags");
+ bstr flag;
+ while (bstr_split_tok(flags, "+", &flag, &flags) || flag.len) {
+ if (bstr_equals0(flag, "default")) {
+ sh->default_track = true;
+ } else if (bstr_equals0(flag, "forced")) {
+ sh->forced_track = true;
+ } else {
+ mp_warn(log, "Unknown flag: '%.*s'\n", BSTR_P(flag));
+ }
+ }
} 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;
@@ -245,7 +273,15 @@ static struct tl_root *parse_edl(bstr str, struct mp_log *log)
sh->codec->codec = "null";
sh->codec->disp_w = get_param_int(&ctx, "w", 0);
sh->codec->disp_h = get_param_int(&ctx, "h", 0);
+ sh->codec->fps = get_param_int(&ctx, "fps", 0);
+ sh->codec->samplerate = get_param_int(&ctx, "samplerate", 0);
tl->delay_open = true;
+ } else if (bstr_equals0(f_type, "global_tags")) {
+ for (int n = 0; n < ctx.num_params; n++) {
+ mp_tags_set_bstr(root->tags, ctx.param_names[n],
+ ctx.param_vals[n]);
+ }
+ ctx.num_params = 0;
} else {
mp_err(log, "Unknown header: '%.*s'\n", BSTR_P(f_type));
goto error;
@@ -278,8 +314,10 @@ static struct tl_root *parse_edl(bstr str, struct mp_log *log)
}
if (ctx.error)
goto error;
- for (int n = 0; n < ctx.num_params; n++)
- mp_warn(log, "Unknown parameter: '%.*s'\n", BSTR_P(ctx.param_names[n]));
+ for (int n = 0; n < ctx.num_params; n++) {
+ mp_warn(log, "Unknown or duplicate parameter: '%.*s'\n",
+ BSTR_P(ctx.param_names[n]));
+ }
}
assert(root->num_pars);
for (int n = 0; n < root->num_pars; n++) {
@@ -360,6 +398,7 @@ static void resolve_timestamps(struct tl_part *part, struct demuxer *demuxer)
}
static struct timeline_par *build_timeline(struct timeline *root,
+ struct tl_root *edl_root,
struct tl_parts *parts)
{
struct timeline_par *tl = talloc_zero(root, struct timeline_par);
@@ -371,8 +410,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");
@@ -509,6 +552,11 @@ static struct timeline_par *build_timeline(struct timeline *root,
if (!root->meta)
root->meta = tl->track_layout;
+ // Not very sane, since demuxer fields are supposed to be treated read-only
+ // from outside, but happens to work in this case, so who cares.
+ if (root->meta)
+ mp_tags_merge(root->meta->metadata, edl_root->tags);
+
assert(tl->num_parts == parts->num_parts);
return tl;
@@ -548,7 +596,7 @@ static void build_mpv_edl_timeline(struct timeline *tl)
for (int n = 0; n < root->num_pars; n++) {
struct tl_parts *parts = root->pars[n];
fix_filenames(parts, tl->demuxer->filename);
- struct timeline_par *par = build_timeline(tl, parts);
+ struct timeline_par *par = build_timeline(tl, root, parts);
if (!par)
break;
all_dash &= par->dash;