Commit Graph

1307 Commits

Author SHA1 Message Date
mg 24acddbdc4 demuxer-lavf: udp_multicast rtsp-transport option 2020-03-03 18:31:20 +01:00
wm4 b31a5e3a58 demux: another hack to deal with track switching refresh
The demuxer cache employs a strange method to make track switching
instant with caching enabled. Normally this would mean you have to wait
until the cache has played out (and you get new packets, including
packets from the newly selected track), or you have to perform a slow
high level seek (decoding video again etc.). The strange method is that
it performs a demuxer-level seek without a high level seek so it looks
like a continuous stream to the decoder, and the newly select stream
gets packets at the current playback position. This is called a refresh
seek.

This works only if some weird heuristics work. It needs a packet "unique
ID", for which it uses either dts or pts. The value must be strictly
monotonic increasing. If this doesn't work, the referesh seek can't be
executed, and the user has to wait until the end of the cache. Sometimes
there are files that simply do not work.

In the present case, there's actually a hack that we can extend. Packets
with unset position are likely generated by the parser, and the hack
which this commit touches simply attempts to make up a new (hopefully
unique) position value, even if the value itself makes no sense. It only
ha to be deterministic.

It turns out libavcodec sometimes output packets with repeating position
values. This commit tries to handle this case too with the same hack.

Fixes: #7498
2020-02-29 23:03:39 +01:00
wm4 c79619f110 demux: add a way to block reading after seeks
Preparation for a future commit. The demuxer queues might be read from
other threads than the one to issue the seek, and passing SEEK_BLOCK
with such a seek will provide a convenient way to synchronize this.
2020-02-29 21:49:00 +01:00
wm4 d32ce14d2c demux_lavf: don't interpret errors as EOF
It seems sporadic errors are possible, such as connection timeouts.
Before the recent demuxer change, the demuxer thread retried many times
even on EOF, so an error was only interpreted as EOF once the decoder
queues ran out.

Change it to use EOF only. Since this may actually lead to the demuxer
thread being "stuck" and retrying forever (depending on libavformat API
behavior), I'm also adding a heuristic to prevent this, using a random
retry counter. This should not be necessary, but libavformat cannot be
trusted. (This retrying forever could be stopped by the user, but
obviously it would still heat the CPU for a longer time if the user is
not present.)
2020-02-28 17:25:07 +01:00
wm4 3ae4094ec0 demux: make seek ranges work for static images + audio
In this case the video track has seek_start == seek_end, and due to the
"seek_start >= seek_end" condition, this was considered broken, and no
seek range was created, breaking cached seeking.

Fix this by allowing the case if they're equal, and a valid timestamp.

(NB: seeking backward in this will still jump to position 0, because it
is the video timestamp. This is unfortunately how it's supposed to work.
HR-seeks will also do this, but decode and skip the entire audio until
the seek target, so it will mostly appear to work.)
2020-02-28 00:59:11 +01:00
wm4 2b628d4352 demux_timeline: fix bad EOF reporting
Exposed by commit b56e2efd5f. demux_timeline reported a bogus EOF if
"parallel" streams were used. If a virtual source reported EOF, it was
propagated as global EOF, without serving packets of other virtual
sources that have not ended yet.

Fix this by not reporting global EOF just because a source has not
returned a packet. Instead make the reader retry by returning no packet
and no EOF state, which will call d_read_packet() again with a different
source. Rely on the eof_reached flags to signal global EOF.

Since eof_reached is now more important, set it in a certain other case
when it apparently should have been set. do_read_next_packet()'s return
value is now ignored, so get rid of it.
2020-02-28 00:08:36 +01:00
wm4 05564af1ac demux_mkv: document probe-start-time option and enable it by default
This is useful with live streams, and it's not much worse than the h264
first packet hack, which reads some data anyway.

For some reason, the option wasn't even documented, so do that.

In addition, print the start time even if it's negative. That should not
be possible, but for some reason, the field is an int64_t copied from an
uint64_t so... whatever. Keeping the logging slightly more straight
forward is better anyway.
2020-02-27 22:30:46 +01:00
wm4 b56e2efd5f demux: simplify some internals, stop trying to read packets after EOF
Remove some redundant fields that controlled or indicated whether the
demuxer was/could/should prefetch. Redefine how the eof/reading fields
work.

The in->eof field is now always valid, instead of weirdly being reset to
false in random situations. The in->reading field now corresponds to
whether the demuxer thread is working at all, and is reset if it stops
doing anything.

Also, I always found it stupid that dequeue_packet() forced the demuxer
thread to retry reading if it was EOF. This makes little sense, but was
probably added for files that are being appended to (running downloads).
It makes no sense, because if the cache really tried to read until file
EOF, it would encounter partial packets and throw errors, so all is lost
anyway. Plus stream_file now handles this better. So stop this behavior,
but add a temporary option that enables the old behavior.

I think checking for ds->eager when enabling prefetching never really
made sense (could be debated, but no, not really). On the other hand,
the change above exposed a missing wakeup in the backward demuxing code.

Some chances of regressions that could make it stuck in certain states
or so, or incorrect demuxer cache state reporting to the player
frontend.
2020-02-27 22:30:46 +01:00
wm4 cf2b7a4997 sub, demux: improve behavior with negative subtitle delay/muxed subs
A negative subtitle delay means that subtitles from the future should be
shown earlier. With muxed subtitles, subtitle packets are demuxed along
with audio and video packets. But since they are demuxed "lazily",
nothing guarantees that subtitle packets from the future are available
in time.

Typically, the user-observed effect is that subtitles do not appear at
all (or too late) with large negative --sub-delay values, but that using
--cache might fix this.

Make this behave better. Automatically extend read-ahead to as much as
needed by the subtitles. It seems it's the easiest to pass the subtitle
render timestamp to the demuxer in order to guarantee that everything is
read. This timestamp based approach might be fragile, so disable it if
no negative sub-delay is used.

As far as the player frontend part is concerned, this makes use of the
code path for external subtitles, which are not lazily demuxed, and may
already trigger waiting.

Fixes: #7484
2020-02-27 02:23:58 +01:00
wm4 b873f1f8e5 demux: avoid some queue management corner cases with subtitles
Subtitle tracks are usually "lazy" (ds->eager=false), There are a number
of weird special cases associated with it. One of them is that they have
some sort of "temporary" EOF (to signal that there isn't a packet right
now, and the decoder should not block playback by waiting for more
packets). In a the next commit, I want to call mark_stream_eof() in case
of (some) of these temporary EOFs.

The problem is that mark_stream_eof() also calls the functions touched
by this commit. Basically they shouldn't do any complex work due to
these temporary EOFs (because they might happen very often). It turns
out that lazy tracks barely matter here: they do not extend the seek
range of a packet/EOF happens on them, they do not trigger seek range
joining, and they do not support backward demuxing.

This change should enable the following commit, while not causing any
behavior changes (i.e. bugs) with the current state.
2020-02-27 02:15:21 +01:00
wm4 605e1fb766 ytdl_hook, edl: add fps, samplerate codec parameters
Well, didn't help much in the case I was interested it.
2020-02-21 14:48:23 +01:00
wm4 a77780e6be edl: make it possible to set the track "default" flag
Also, the forced flag (and in the future, potentially a number of other
flags not implemented yet). See next commit for purpose.
2020-02-21 14:16:26 +01:00
wm4 9f5b9011d6 demux_edl: correct warning on duplicate parameters
A parameter that is actually used is removed from the param_names[]
array, so we can report unused parameters. This also happened on
duplicate parameters, so adjust the warning to make it less confusing.

(In any case, you're not supposed to provide duplicate parameters.)
2020-02-21 12:05:29 +01:00
wm4 6f0297dff4 edl: make it possible to delay-load files with multiple tracks
Until now, delay-loading was for files with single tracks only
(basically what DASH and HLS like to expose, so adaptive streaming and
codec selection becomes easier - for sites, not for us). But they also
provide some interleaved versions, probably for compatibility. Until
now, we were forced to eagerly load it (making startup slightly slower).

But there is not much missing. We just need a way to provide multiple
metadata entries, and use them to represent each track.

A side effect is now that the "track_meta" header can be used for normal
EDL files too.
2020-02-21 00:19:17 +01:00
wm4 6726b7a1ba demux_lavf: signal no seeking for RTSP streams without duration
RTSP supports seeking, but at least the libavformat implementation makes
this dependent on runtime behavior. So you have to perform a seek, and
check if it fails. But even if you do this, the stream is interrupted
and restarted, and there seem to be other issues.

Assume that RTSP with unknown duration means it's a live stream, and
disable seeking in this case, as suggested by the issue reporter.

Fixes: #7472
2020-02-20 15:28:49 +01:00
wm4 bd6d8d320f demux_timeline: don't open every delayed-open track on seeking
Now this was stupid. To seek a source, it obviously has to be opened...
so just don't try to seek any unused source. If the track is actually
selected during playback, a seek to the correct position is performed
anyway.
2020-02-20 15:21:27 +01:00
wm4 0020b47ffd demux: fix seek range caching with delay_open hack
These have ->segmented set (so the codec can be initialized properly),
but have no segment start or end times. This code was (probably) the
only thing which didn't handle this case.
2020-02-20 15:11:46 +01:00
wm4 e64645540a demux_timeline: warn if streams are invisible
ytdl_hook.lua can do this with all_formats and when delay_open is used,
and if the source stream actually contains both audio and video. In this
case, it might accidentally hide a media type completely, or waste
bandwidth (if the stream has true interleaved audio/video). So it's
important to warn.
2020-02-20 12:16:32 +01:00
wm4 b8f80b3854 player: print manifest per-stream bitrate information to terminal
Aka hls-bitrate. In turn, remove the demux_lavf.c hack, which made the
track title use this.
2020-02-19 16:26:22 +01:00
wm4 fbc226af51 demux: cosmetic change
This was sort of asymmetric and annoying.
2020-02-17 00:04:56 +01:00
wm4 26ec5862b3 demux: update file-size property even when paused
While paused, the decoders typically stop reading data from the demuxer.
But for some reason, the file size is returned as a public field in
struct demuxer (wat...), and updated only when the packet reading
function is called. This caused the file size property to always return
the same value when paused, even though the demuxer thread was reading
new data, and the internal file size was updated.

Fix with a simple hack.
2020-02-16 23:59:21 +01:00
wm4 1a54339705 demux: only query stream size at most once per second
Instead of every packet. Doing it every packet led to the performance
regression mentioned in the fstat() commit. This should now be over, but
out of being careful, don't query the file size that often. This is only
used for user interface things, so this should not cause any problems.

For the sake of leaving the code compact, abuse another thing that is
updated only every second (speed statistics).
2020-02-16 23:49:42 +01:00
wm4 27bf978e75 demux: invert update_cache() locking
Equivalent, just slightly more convenient for the following change.
2020-02-16 23:43:13 +01:00
wm4 7d11eda72e Remove remains of Libav compatibility
Libav seems rather dead: no release for 2 years, no new git commits in
master for almost a year (with one exception ~6 months ago). From what I
can tell, some developers resigned themselves to the horrifying idea to
post patches to ffmpeg-devel instead, while the rest of the developers
went on to greener pastures.

Libav was a better project than FFmpeg. Unfortunately, FFmpeg won,
because it managed to keep the name and website. Libav was pushed more
and more into obscurity: while there was initially a big push for Libav,
FFmpeg just remained "in place" and visible for most people. FFmpeg was
slowly draining all manpower and energy from Libav. A big part of this
was that FFmpeg stole code from Libav (regular merges of the entire
Libav git tree), making it some sort of Frankenstein mirror of Libav,
think decaying zombie with additional legs ("features") nailed to it.
"Stealing" surely is the wrong word; I'm just aping the language that
some of the FFmpeg members used to use. All that is in the past now, I'm
probably the only person left who is annoyed by this, and with this
commit I'm putting this decade long problem finally to an end. I just
thought I'd express my annoyance about this fucking shitshow one last
time.

The most intrusive change in this commit is the resample filter, which
originally used libavresample. Since the FFmpeg developer refused to
enable libavresample by default for drama reasons, and the API was
slightly different, so the filter used some big preprocessor mess to
make it compatible to libswresample. All that falls away now. The
simplification to the build system is also significant.
2020-02-16 15:14:55 +01:00
wm4 c92c08edc6 edl: add mechanism for delay loading streams
Add something that will access an URL embedded in EDL only when the
track it corresponds to is actually selected. This is meant to help with
ytdl_hook.lua and to improve loading speeds.

In theory, all this stuff is available to any mpv user, but discourage
using it, as it's so specialized towards ytdl_hook.lua, that there's
danger we'll just break this once ytdl_hook.lua stops using it, or
similar.

Mostly untested.
2020-02-15 18:29:44 +01:00
wm4 1d53a8f2e7 demux_edl: warn if no_clip is used with multiple parts
Well whatever.
2020-02-15 15:25:12 +01:00
wm4 921f316281 demux_edl: allow a redundant new_stream at the beginning
Normally, the first sub-stream is implicitly created. This change lets
the user use more orthogonal syntax, and use a new_stream header for
every sub-stream, instead of having to skip the header for the first
one.
2020-02-15 15:22:05 +01:00
wm4 64c4c59770 demux_edl: accept protocol entries in EDL entries again
Accidentally broken by commit 99700bc52c. mp_path_join() does not
check for this, because it's supposed to work on filesystem strings (and
e.g. "http://fubar" is a valid relative path in UNIX).
2020-02-15 15:11:05 +01:00
wm4 96ef62161a demux_edl: improve parsing slightly
Add a mp_log context to the parse_edl() function, and report some
errors. Previously, this just told you that something was wrong. Add
some error reporting to make it slightly less evil.

Put all parameters in a list before processing them. This makes adding
parameters for special headers easier, and we can report parameters that
were not understood. (For "compatibility", which probably doesn't matter
at all, still don't count them as errors; as before.)
2020-02-15 15:07:52 +01:00
wm4 121bc6ad62 demux_timeline: fix another cursed memory management issue
The timeline stuff has messed up memory management because there are no
clear ownership rules between a some demuxer instances (master or
demux_timeline) and the timeline object itself.

This is another subtle problem that happened: apparently,
demux_timeline.open is supposed to take over ownership of timeline, but
only on success. If it fails, it's not supposed to free it. It didn't
follow this, which lead to a double-free if demux_timeline.open failed.
The failure path in demux.c calls both timeline_destroy() and
demux_timeline.close on failure.
2020-02-15 14:07:46 +01:00
wm4 64a03b03ea demux_timeline: fix a comment 2020-02-15 13:55:54 +01:00
wm4 d5de8ddb65 demux_timeline: reorder some functions
Move them around in the source code to get rid of the forward
declarations. Other than rearranging the lines and removing the 2
forward declarations, there are no other changes at all.
2020-02-15 13:55:37 +01:00
wm4 27d5d32020 demux: add option to disable "sharing" between back and forward buffers
As requested. I guess option name and manpage text could be better and
clearer.

Closes: #7442
2020-02-07 15:58:13 +01:00
wm4 cbee577d0a cue: tolerate NBSP as whitespace
Apparently such .cue files exist. They fail both probing and parsing. To
make it worse, the sample at hand was encoded as Latin1.

One part of this is replacing bstr_lstrip() with a version that supports
NBSP. One could argue that bstr_lstrip() should always do this, but I
don't want to overdo it. There are many more unicode abomination which
it could be said it's supposed to handle, so it will stay ASCII instead
of going down this rabbit hole. I'm just assuming this cue sheet was
generated by some stupid software that inexplicably liked NBSPs (which
is how we justify a one-off fix). The new lstrip_whitespace() doesn't
look particularly efficient, but it doesn't have to be.

The second part is dealing with the fact that the charset is not
necessarily UTF-8. We don't want to do conversion before probing thinks
it knows it's a cue sheet (would probably make it more fragile all
around), so just make it work with Latin1 by assuming invalid code
points are Latin1. This fallback is part of why lstrip_whitespace() is
sort of roundabout.

(You could still rewrite it as much more efficient state machine,
instead of using a slow and validating UTF-8 parser that is called per
codepoint. Starting to overthink this.)

Multimedia is terrible. Legacy charsets are terrible. Everything is
terrible.

Fixes: #7429
2020-02-03 19:13:44 +01:00
wm4 1b283f6b60 libarchive: some shitty hack to make opening slightly faster
See manpage additions. The libarchive behavior mentioned in the last
paragraph there is technically unrelated, but makes this new option
mostly pointless.

See: #7182
2020-01-04 19:56:09 +01:00
wm4 5016a1e4a6 demux: add per-demuxer sub-options
Until now, they were all just added to options.c (e.g. demux_mkv_conf).
This adds a mechanism which can be used to add future options in a
(very) slightly more elegant way.
2020-01-04 19:47:36 +01:00
wm4 04bde06095 stream_libarchive: some more hacks to improve multi-volume archives
Instead of opening every volume on start just to see if it's there, all
all volumes that could possibly exist, and "handle" it on opening. This
requires working around some of libarchive's amazing stupidity and using
some empirically determined behavior. Will possibly break if libarchive
changes some of this behavior.

See: #7182
2020-01-04 18:59:23 +01:00
wm4 99700bc52c demux_edl: restore relative path resolution
Playing e.g. "dir/f.edl" should make all non-absolute paths in f.edl
relative to "dir".

Commit 0e98b2ad8e accidentally broke this.
2020-01-02 23:31:02 +01:00
wm4 3b6c4e7be1 demux: make track switching instant with certain mpegts files
When switching tracks, the data for the new track is missing by the
amount of data prefetched. This is because all demuxers return
interleaved data, and you can't just seek the switched track alone.
Normally, this would mean that the new track simply gets no data for a
while (e.g. silence if it's an audio track). To avoid this, mpv performs
a special "refresh seek" in the demuxer, which tries to resume demuxing
from an earlier position, in a way that does not disrupt decoding for
the non-changed tracks. (Could write a lot about the reasons for doing
something so relatively complex, and the alternatives and their
weaknesses, but let's not.)

This requires that the demuxer can tell whether a packet after a seek
was before or after a previously demuxed packet, sort of like an unique
ID. The code can use the byte position (pos) and the DTS for this. The
DTS is normally strictly monotonically increasing, the position in most
sane file formats too (notably not mp4, in theory).

The file at hand had DTS==NOPTS packets (which is fine, usually this
happens when PTS can be used instead, but the demux.c code structure
doesn't make it easy to use this), and pos==-1 at the same time. The
latter is what libavformat likes to return when the packet was produced
by a "parser" (or in other words, packets were split or reassembled),
and the packet has no real file position. That means the refresh seek
mechanism has no packet position and can't work.

Fix this by making up a pseudo-position if it's missing. This needs to
set the same value every time, which is why it does not work for
keyframe packets (which, by definition, could be a seek target).

Fixes: #7306 (sort of)
2019-12-31 00:17:46 +01:00
wm4 f0d0822595 demux: fix --stream-record runtime change handling
Well, if that wasn't particularly dumb.
2019-12-29 20:18:35 +01:00
wm4 582f3f7cc0 playlist: change from linked list to an array
Although a linked list was ideal at first, there are cases where it
sucks, and became increasingly awkward (with the mpv command API
preferring integer indexes to access the list). In future, we probably
want to add more playlist-related functionality, so better change it to
an array now.

An array isn't always ideal either. Since playlist entries are still
separate objects (because in some cases you need a stable "iterator" to
it), but you still need to efficiently get the next/previous playlist
entry, there's a pl_index field, that needs to be maintained. E.g.
adding an entry at the start of the playlist => update the pl_index
field for all other entries. Well, it's not really worth to do something
more complicated to avoid these things.

This commit is probably buggy as shit. It's not like I bothered to test
everything. That's _your_ role.
2019-12-28 21:32:15 +01:00
wm4 36da3325a3 demux: stop setting dummy stream on demux_close_stream()
Demuxers can call demux_close_stream() to close the underlying stream if
it's not needed anymore. (Useful to release "heavy" resources like FDs
and sockets. Plus merely keeping a file open can have visible side
effects such as inability to unmount a filesystem or, on Windows, to do
anything with the file.)

Until now, this set demuxer->stream to a dummy stream, because most code
used to assume that the stream field is non-NULL. But this requirement
disappeared (in some cases, the stream field is already NULL), so stop
doing that. demux_lavf.c, one of the demuxers which calls this function,
still had some of this, though.
2019-12-23 11:09:42 +01:00
wm4 cd09ea92be demux_mf: use stream API to open list files
mf:// has an obscure feature that lets you pass a list of filenames
separated by newlines. Who knows whether anyone is using that. It opened
these listfiles with fopen(), so the recent stream origin bullshit
doesn't operate on it. Fix this by using the mpv internal stream API
instead. Unfortunately there is no fgets(), so write an ad-hoc one. (An
implementation of line reading via "stream" is still in demux_playlist,
but it's better to keep it quarantined there.)
2019-12-23 11:01:29 +01:00
wm4 9e15e3ad8f demux: remove debug abort()
WHAT THE FUCK

Fixes: #7279
2019-12-22 04:57:18 +01:00
wm4 8448fe0b62 demux: add an option to control tag charset
Fucking gross that you need this in almost-2020.

Fixes: #7255
2019-12-20 13:00:39 +01:00
wm4 0e98b2ad8e edl: accept arbitrary paths
Until now, .edl files accepted only "simple" filenames, i.e. no relative
or absolute paths, no URLs. Now that the origin bullshit is a bit
cleaned up and enforced in the EDL code, there's absolutely no reason to
keep this.

The new code behaves somewhat similar to playlists. (Although playlists
are special because they're not truly recursively opened.)
2019-12-20 13:00:39 +01:00
wm4 1cb9e7efb8 stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)

It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.

The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
  ("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this

This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.

I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).

There may be a lot of bugs in this.

This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit

Fixes: #7274
2019-12-20 13:00:39 +01:00
wm4 572c32abbe libarchive: prefix entry names in archive URLs with '/'
This has the advantage that playlists within the archive will work as
expected, because demux_playlist will correctly join the archive base
URL and entry name. Before this change, it could skip before the "|",
resulting in a broken URL.
2019-12-20 08:35:08 +01:00
wm4 0bf0efd6d3 demux_edl: fix reusing segment source files
EDL files can have multiple segments taken from the same source file. In
this case, the source file is supposed to be opened only once. This
stopped working, and it created a new demuxer instance for every single
segment entry. This made it slow and made it use much more memory than
needed.

This was because it tried to iterate over the array of source files, but
the array count (num_parts) was only set to a non-0 value later. Fix
this by maintaining the count correctly.

In addition, the actual code for checking whether a source can be reused
(in open_source()) regressed and stopped working correctly. d->stream
could be NULL. Use demuxer.filename instead; I'm not entirely sure
whether this is always correct, but fortunately we have a distributed
almost-AI driven test suite (called "users") which will probably find
and report such cases.

Probably broke with commit a09396ee60 or something close, but didn't
check closer.

Fixes: #7267
2019-12-17 01:57:42 +01:00
wm4 d60bbd86e3 demux_lavf: export demuxer_id for more formats which have it
See previous commit. libavformat exports this information as AVStream.id
field.

The big problem is that the libavformat field is simply 0 if it's
unknown (i.e. the demuxer never sets it). So it needs to remain a
whitelist. Just add more formats which are known to have a meaningful
ID.

I considered exporting IDs for all formats, and then either leaving the
values as they are, or filtering duplicate values (and choosing
arbitrary but unique different IDs). But then again, I think it's sort
of mpv's job to filter FFmpeg's absurd bullshit API, and it should make
an effort to hide it rather than to reflect it.

See: #7211
2019-12-03 21:15:40 +01:00