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.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/demux/demux_edl.c b/demux/demux_edl.c
index 6e1af373ee..e71c1dfd99 100644
--- a/demux/demux_edl.c
+++ b/demux/demux_edl.c
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
+#include <limits.h>
#include <math.h>
#include "mpv_talloc.h"
@@ -47,8 +48,9 @@ struct tl_part {
struct tl_parts {
bool disable_chapters;
- bool dash, no_clip;
+ bool dash, no_clip, delay_open;
char *init_fragment_url;
+ struct sh_stream *sh_meta;
struct tl_part *parts;
int num_parts;
struct tl_parts *next;
@@ -102,6 +104,24 @@ static char *get_param0(struct parse_ctx *ctx, void *ta_ctx, const char *name)
return bstrdup0(ta_ctx, get_param(ctx, name));
}
+// Optional int parameter. Returns the parsed integer, or def if the parameter
+// is missing or on error (sets ctx.error on error).
+static int get_param_int(struct parse_ctx *ctx, const char *name, int def)
+{
+ bstr val = get_param(ctx, name);
+ if (val.start) {
+ bstr rest;
+ long long ival = bstrtoll(val, &rest, 0);
+ if (!val.len || rest.len || ival < INT_MIN || ival > INT_MAX) {
+ MP_ERR(ctx, "Invalid integer: '%.*s'\n", BSTR_P(val));
+ ctx->error = true;
+ return def;
+ }
+ return ival;
+ }
+ return def;
+}
+
// Optional time parameter. Currently a number.
// Returns true: parameter was present and valid, *t is set
// Returns false: parameter was not present (or broken => ctx.error set)
@@ -125,6 +145,8 @@ 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;
}
@@ -200,6 +222,30 @@ static struct tl_root *parse_edl(bstr str, struct mp_log *log)
tl = add_part(root);
} 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;
+ 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;
+ bstr mt = get_param(&ctx, "media_type");
+ if (bstr_equals0(mt, "video")) {
+ sh->type = sh->codec->type = STREAM_VIDEO;
+ } else if (bstr_equals0(mt, "audio")) {
+ sh->type = sh->codec->type = STREAM_AUDIO;
+ } else if (bstr_equals0(mt, "sub")) {
+ sh->type = sh->codec->type = STREAM_SUB;
+ } else {
+ mp_err(log, "Invalid or missing !delay_open media type.\n");
+ goto error;
+ }
+ sh->codec->codec = get_param0(&ctx, sh, "codec");
+ if (!sh->codec->codec)
+ sh->codec->codec = "null";
+ sh->codec->disp_w = get_param_int(&ctx, "w", 0);
+ sh->codec->disp_h = get_param_int(&ctx, "h", 0);
+ tl->delay_open = true;
} else {
mp_err(log, "Unknown header: '%.*s'\n", BSTR_P(f_type));
goto error;
@@ -322,6 +368,11 @@ static struct timeline_par *build_timeline(struct timeline *root,
tl->track_layout = NULL;
tl->dash = parts->dash;
tl->no_clip = parts->no_clip;
+ 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;
if (parts->init_fragment_url && parts->init_fragment_url[0]) {
MP_VERBOSE(root, "Opening init fragment...\n");
@@ -366,6 +417,15 @@ static struct timeline_par *build_timeline(struct timeline *root,
if (!tl->track_layout)
tl->track_layout = open_source(root, tl, part->filename);
+ } else if (tl->delay_open) {
+ if (n == 0 && !part->offset_set) {
+ part->offset = starttime;
+ part->offset_set = true;
+ }
+ if (part->chapter_ts || (part->length < 0 && !tl->no_clip)) {
+ MP_ERR(root, "Invalid specification for delay_open stream.\n");
+ goto error;
+ }
} else {
MP_VERBOSE(root, "Opening segment %d...\n", n);
@@ -444,7 +504,7 @@ static struct timeline_par *build_timeline(struct timeline *root,
}
}
- if (!tl->track_layout)
+ if (!tl->track_layout && !tl->delay_open)
goto error;
if (!root->meta)
root->meta = tl->track_layout;