diff options
-rw-r--r-- | DOCS/edl-mpv.rst | 30 | ||||
-rw-r--r-- | demux/demux_edl.c | 18 |
2 files changed, 47 insertions, 1 deletions
diff --git a/DOCS/edl-mpv.rst b/DOCS/edl-mpv.rst index ec8dce01cc..c5771c2bca 100644 --- a/DOCS/edl-mpv.rst +++ b/DOCS/edl-mpv.rst @@ -216,6 +216,36 @@ Example:: The virtual timeline will have two chapters, one called "cap.ts" from 0-240s and a second one called "Show Opening" from 240-330s. +Entry which defines the track layout +==================================== + +Normally, you're supposed to put only files with compatible layouts into an EDL +file. However, at least the mpv implementation accepts entries that use +different codecs, or even have a different number of audio/video/subtitle +tracks. In this case, it's not obvious, which virtual tracks the EDL show should +expose when being played. + +Currently, mpv will apply an arbitrary heuristic which tracks the EDL file +should expose. (Before mpv 0.30.0, it always used the first source file in the +segment list.) + +You can set the ``layout`` option to ``this`` to make a specific entry define +the track layout. + +Example:: + + # mpv EDL v0 + file_with_2_streams.ts,5,240 + file_with_5_streams.mkv,0,90,layout=this + +The way the different virtual EDL tracks are associated with the per-segment +ones is highly implementation-defined, and uses a heuristic. If a segment is +missing a track, there will be a "hole", and bad behavior may result. Improving +this is subject to further development (due to being fringe cases, they don't +have a high priority). + +If future versions of mpv change this again, this option may be ignored. + Syntax of EDL URIs ================== diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 205d607427..7016df3558 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -40,6 +40,7 @@ struct tl_part { double offset; // offset into the source file bool offset_set; bool chapter_ts; + bool is_layout; double length; // length of the part (-1 if rest of the file) char *title; }; @@ -151,6 +152,9 @@ static struct tl_root *parse_edl(bstr str) p.chapter_ts = true; } else if (bstr_equals0(name, "title")) { p.title = bstrto0(tl, val); + } else if (bstr_equals0(name, "layout")) { + if (bstr_equals0(val, "this")) + p.is_layout = true; } } nparam++; @@ -357,10 +361,22 @@ static struct timeline_par *build_timeline(struct timeline *root, starttime = tl->parts[n].end; - if (source && !tl->track_layout) + if (source && !tl->track_layout && part->is_layout) tl->track_layout = source; } + if (!tl->track_layout) { + // Use a heuristic to select the "broadest" part as layout. + for (int n = 0; n < parts->num_parts; n++) { + struct demuxer *s = tl->parts[n].source; + if (!s) + continue; + if (!tl->track_layout || + demux_get_num_stream(s) > demux_get_num_stream(tl->track_layout)) + tl->track_layout = s; + } + } + if (!tl->track_layout) goto error; if (!root->meta) |