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
See manpage additions. The libarchive behavior mentioned in the last
paragraph there is technically unrelated, but makes this new option
mostly pointless.
See: #7182
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.
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
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)
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.
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.
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.)
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.)
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
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.
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
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
The demuxer_id (exported in as "src-id" property) is supposed to be the
native stream ID, as it exists in the file, or -1 if that does not exist
(actually any negative value), or if it is unknown.
Until now, an ID was made up if it was missing. That seems like strange
non-sense, and I can't find the reason why it was done. But it was
probably for convenience by the EDL stuff or so.
Stop doing this. Fortunately, the src-id property was documented as
being unavailable if the ID is not known. Even the code for this was
present, it was just inactive until now. Extend input.rst with some
explanations.
Also fixing 3 other places where negative demuxer_id was ignored or
avoided.
Just an implementation detail that can be cleaned up now. Internally,
m_config maintains a tree of m_sub_options structs, except for the root
it was not defined explicitly. GLOBAL_CONFIG was a hack to get access to
it anyway. Define it explicitly instead.
If SEEK_FORWARD is set, a demuxer should skip to the next frame if the
timestamp does not fall on the start of a frame. If that flag is not
set, it should always seek to the first frame before the target
timestamp (or the first frame in the file).
It sometimes happens that HLS streams freeze because the HTTP server is
not responding for a fragment (or something similar, the exact
circumstances are unknown). The --timeout option didn't affect this,
because it's never set on HLS recursive connections (these download the
fragments, while the main connection likely nothing and just wastes a
TCP socket).
Apply an elaborate hack on top of an existing elaborate hack to somehow
get these options set. Of course this could still break easily, but hey,
it's ffmpeg, it can't not try to fuck you over. I'm so fucking sick of
ffmpeg's API bullshit, especially wrt. HLS.
Of course the change is sort of pointless. For HLS, GET requests should
just aggressively retried (because they're not "streamed", they're just
actual files on a CDN), while normal HTTP connections should probably
not be made this fragile (they could be streamed, i.e. they are backed
by some sort of real time encoder, and block if there is no data yet).
The 1 minute default timeout is too high to save playback if this
happens with HLS.
Vaguely related to #5793.
Until now, we've made FFmpeg use the default network timeout - which is
apparently infinite. I don't know if this was changed at some point,
although it seems likely, as I was sure there was a more useful default.
For most use cases, a smaller timeout is more useful (for example
recording something in the background), so force a timeout of 1 minute.
See: #5793
stream_skip() semantics were kind of bad, especially after the recent
change to the stream code. Forward stream_skip() calls could still
trigger a seek and fail, even if it was supposed to actually skip data.
(Maybe the idea that stream_skip() should try to seek is worthless in
the first place.)
Rename it to stream_seek_skip() (takes absolute position now because I
think that's better), and make it always skip if the stream is marked as
forward.
While we're at it, make EOF detection more robust. I guess s->eof
shouldn't exist at all, since it's valid only "sometimes". It should be
removed... but not today. A 1-byte stream_read_peek() call is good to
get the s->eof flag set to a correct value.
demux_mkv was the only thing using this, and everything else accessed it
directly. No need to keep the indirection wrapper around.
(Funny how this getter was in the initial commit of MPlayer.)
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.
Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).
In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).
Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.
I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.
It also contains bugs; you're an alpha tester now.
The old code made it depend on ->seekable. If it isn't seekable, and
something discarded the data, then it'll just show an error message,
which will at least be somewhat informative. If no data was discarded,
the seek call is always a no-op.
There's a weird "timeline" condition in the old code; this doesn't
matter anymore, because timeline stuff does not pass streams down to
nested demuxers anymore.
demux_mkv has lots of logging that shows information about the file. It
sort of reminds of mkvinfo output. While this is sometimes interesting,
it's too much for verbose mode, and should be in debug log level.
This can be used by distros to disable all known FFmpeg ABI violations.
Currently only 1 is known, in demux_lavf.c. In addition to if-defing out
the access to the private FFmpeg field, this disables the possibly
fragile nested open callbacks, which make sense only if the
aforementioned field can be accessed.
In pseudo-DASH mode, we may have no real streams opened until the
demuxer layer is fully loaded and playback actually starts. The only
hint that the stream is from network is, at that point, the init
segment, which is only opened as stream, and then separately as demuxer
(which is dumb but happened to fit the internal architecture better).
So just propagate the flags from the init segment stream. Seems like an
annoyance, but doesn't hurt that much I guess. (Until someone gets the
idea to pass the init segment data inline or so, but nothing does that.)
The sample link in the linked issue will probably soon switch to another
format, because that service always does this after recent uploads or
so.
Fixes: #7038
Someone crazy is trying to mix images with videos in EDL files. Putting
an image as first thing into the EDL disabled audio, because the first
EDL entry was used to define the layout.
Change this. Make it user-configurable, and use a "better" heuristic to
select the default otherwise.
In theory, EDL could be easily extended to specify track layout and
mapping of parts to virtual EDL tracks manually and in great detail. But
I don't think it's worth it - who would bother using it?
Fixes: #6764
This partially reverts commit a9d83eac40
("Remove optical disc fancification layers").
Mostly due to the timestamp crap, this was never really going to work.
The playback layer is sensitive to timestamps, and derives the playback
time directly from the low level packet timestamps. DVD/BD works
differently, and libdvdnav/libbluray do not make it easy at all to
compensate for this. Which is why it never worked well, but not doing it
at all is even more awful.
demux_disc.c tried this and rewrote packet timestamps from low level TS
to playback time. So restore demux_disc.c, which should bring behavior
back to the old often non-working but slightly better state.
I did not revert anything that affects components above the demuxer
layer. For example, the properties for switching DVD angles or listing
disc titles are still gone. (Disc titles could be reimplemented as
editions. But not by me.)
This commit modifies the reverted code a bit; this can't be avoided,
because the internal API changed quite a bit. The old seek resync in
demux_lavf.c (which was a hack) is replaced with a hack. SEEK_FORCE and
demux_params.external_stream are new additions.
Some of this could/should be further cleaned up. If you don't want
"proper" DVD/BD support to disappear, you should probably volunteer.
Now why am I wasting my time for this? Just because some idiot users are
too lazy to rip their ever-wearing out shitty physical discs? Then why
should I not be lazy and drop support completely? They won't even be
thankful for me maintaining this horrible garbage for no compensation.
This was added in 585f9ff42f by @bbarenblat (github handle). We
don't do this. This file alone probably has multiple dozen of authors (I
didn't count, but it has a history of 15 years). If everyone added their
names with each small change, this project would have giant lists of
contributing authors on every source file.
Neither copyright law nor any of the used licenses require listing
authors in the license header. Authorship is recorded in the git log.
So don't start with this, and remove this recent case to avoid setting a
precedent.
Some files still have an author in the header. These cases are
grandfathered, and usually are the actual authors of the original code.
demux_mkv may seek to the end of the file to read certain headers (which
should probably be called "footers", but in theory they are just headers
that have been placed at the end of the file unfortunately).
This commit changes behavior not to seek if the stream is not marked as
seekable. Before this, it only checked whether the stream size was
unknown (end negative). In practice it doesn't make much of a
difference, since seekable usually equals known stream size.
Also improve the wording, and distinguish between actual incomplete
files, and unseekable ones.
This passed all streams to mp_recorder_create(), even disabled ones. The
disabled streams never get packets, so recorder.c eventually errors out
with unrelated-looking errors. The reason is that recorder.c waits for
packets to appear on other streams, which in turn is because libavformat
refuses to mux empty streams anyway.
recorder.c could call demux_stream_is_selected(), which would have made
the patch much smaller. But this feels like a bad idea, since recorder.c
should use sh_stream only for metadata (and not in an "active" way), nor
should it care what demux.c is currently doing with it. So make the API
user (demux.c) pass only the streams it really wants.
Fixes: #6999
Although this was sort of elegant, it just seems to complicate things
slightly. Originally, the API meant that you cache mp_recorder_sink
yourself (which would avoid the mess of passing an index around), but
that too seems slightly roundabout.
In a later change, I want to change the set of streams passed to
mp_recorder_create(), and then I'd have to keep track of the index for
each stream, which would suck. With this commit, I can just pass the
unambiguous sh_stream to it, and it will be guaranteed to match the
correct stream.
The disadvantages are barely worth discussing. It's a new linear search
per packet, but usually only 2 to 4 streams are active at a time. Also,
in theory a user could want to write 2 streams using the same sh_stream
(same metadata, just writing different packets or so), but in practice
this is never done.
in->eof is used as an indicator whether reading packets still makes
sense. (Without this, the prefetcher would obviously burn CPU by
retrying reading even though everything has been read.)
This was not reset properly after seeks were performed. It led to
getting stuck in at least one corner case: when enabling a track, the
demuxer would seek backwards to get new packets from the current
playback position ("refresh seeks"). But if playback was paused, and EOF
was previously reached, it would not try to read packers again due to
in->eof being false. There was not anything else that would make it
retry reading, so it was stuck in a weird underrun/buffering state.
Fixes: #6986
This was a leftover from commit b2752321 which fixed#6522 but after
the recent demux refactoring this fix is superseded by commit 0f6cda4ab.
Remove the redundant update call.
This detected the first packet demuxed after a seek as timestamp
discontinuity. Obviously this is non-sense. Since the OGG radio streams
for which this feature was introduced are normally unseekable, it's
simple to fix this: simply disable it (if in auto mode, the default) as
soon as a seek is performed. This code is never called if the stream is
considered unseekable, unless the user forced it.
There's still a chance this linearization is performed before a seek
happens. This will be a bit awkward, but no worse than without this
feature, since seeking with timestamp resets is inherently broken in
both mpv and libavformat.
Fixes: #6974
Fixes: 27fcd4d