diff options
Diffstat (limited to 'demux/demux_edl.c')
-rw-r--r-- | demux/demux_edl.c | 68 |
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; |