Parsing sub-configs (like --rawvideo=subopts or the suboptions for
--vo=opengl:subopts) was completely different from the -vf parsing code
for a variety of reasons. This change at least makes -vf use the same
splitter code as sub-config options.
The main improvement is that -vf now accepts quotes, so you can write
things like:
-vf 'lavfi=graph="gradfun=10:20"'
(The '' quotes are for shell escaping.)
This is a rather big and intrusive change. Trying some -vf lines from
etc/encoding-example-profiles.conf seems to confirm it still works.
This also attempts to unify one subtle difference in handling of
positional arguments. One consequence is that a minor detail changes.
Sub-configs don't know positional arguments, and something like "--
opt=sub1=val1:sub2" means that sub2 has to be a flag option. In -vf
parsing, sub2 would be a positional option value. To remove this
conflict and to facilitate actual unification of the parsers in the
future, the sub2 will be considered a flag option if and only if such a
flag option exists. Otherwise, it's considered a value for a positional
option.
E.g. if there's a filter "foo" with a string option "sopt" and a flag
option "fopt", the behavior of the following changes:
-vf foo=fopt
Before this commit, this would set "sopt=fopt" in the filter. Now, it
enables the fopt flag, and the sopt option remains unset. This is not an
actual problem to my knowledge.
Remove the "object settings" based track range parsing (needed by
stream_cdda only), and make stream_cdda use CONF_TYPE_INT_PAIR.
This makes the -vf parsing code completely independent from other
options. A bit of that code was used by the mechanism removed with
this commit.
When trying to seek before the start of the file, which usually happens
when using the arrow keys to seek to the start of the file, external
libavformat demuxed subtitles will be invisible. This is because seeking
in the external subtitle file fails, so the subtitle demuxer is left in
a random state.
This is actually similar to the normal seeking path, which has some
fallback code to handle this situation. Add such code to the subtitle
seeking path too.
(Normally, all demuxer support av_seek_frame(), except subtitles, which
support avformat_seek_file() only. The latter was meant to be the "new"
seeking API, but this never really took off, and using it normally seems
to cause worse seeking behavior. Or maybe we just use it incorrectly,
nobody really knows.)
Before this commit, it was more or less random which subtitle was
preferred if there was both an auto-loaded external subtitle, and a
subtitle loaded via -sub or -subfile. -sub subtitles happened to be
preferred over auto-loaded subs, while -subfile didn't. Fix the -subfile
case, and make the behavior consistent by making the selection behavior
explicit.
Get rid of the 1-char subtitle type field. Use sh_stream->codec instead
just like audio and video do. Use codec names as defined by libavcodec
for simplicity, even if they're somewhat verbose and annoying.
Note that ffmpeg might switch to "ass" as codec name for ASS, so we
don't bother with the current silly "ssa" name.
MP_INPUT_BUFFER_PADDING_SIZE and FF_INPUT_BUFFER_PADDING_SIZE are both
16. The doxygen for FF_INPUT_BUFFER_PADDING_SIZE says only the first 23
bits must to be 0, but this is probably a lie.
This removes the stream handling mess by using a single list for all
stream types.
One consequence is that new streams are always set to AVDISCARD_ALL,
which could be an issue if packets are read before initializing other
streams. However, this doesn't seem to an issue for various reasons,
so we don't do anything about it.
The new code strictly assumes that libavformat never removes or
reorders streams once added to AVFormatContext->streams. Undefined
behavior will result if it does.
mkv_track_t now references sh_stream directly, instead of using an ID.
Also remove all accesses to demux_stream (demuxer->video etc.).
Remove some slave-mode things on the way, like "ID_SID_..." messages.
Some preparations to simplify demux_mkv and demux_lavf.
struct demux_stream manages state for each stream type that is being
demuxed (audio/video/sub). demux_stream is rather annoying, especially
the id and sh members, which are often used by the demuxers to determine
current stream and so on. Demuxers don't really have to access this,
except for testing whether a stream is selected and to add packets.
Add a new_sh_stream(), which allows creating streams without having the
caller specify any kind of stream ID. Demuxers should just use sh_stream
pointers, instead of multiple kinds of IDs and indexes.
Since demux_mkv queries the demuxer state when reading packets, track
switching is completely passive. Cycling etc. is done by the frontend.
As result, all track switching code can be removed.
Matroska files can contain multiple segments, which are literally
further Matroska files appended to the main file. They can be referenced
by segment linking.
While this is an extraordinarily useless and dumb feature, we support it
for the hell of it.
This is implemented by adding a further demuxer parameter for skipping
segments. When scanning for linked segments, each file is opened
multiple times, until there are no further segments found. Each segment
will have a separate demuxer instance (with a separate file handle
etc.).
It appears the Matroska spec. has an even worse feature for segments:
live streaming can completely reconfigure the stream by starting a new
segment. We won't add support for it, because there are 0 people on this
earth who think Matroska life streaming is a good idea. (As opposed to
serving Matroska/WebM files via HTTP.)
Matroska segment linking allows abusing Matroska files as playlists
without any actual video/audio/sub data, making files without any
clusters still useful for the frontend.
With Matroska ordered chapters, the main file (i.e. the file you're
playing) can be empty, while all video/audio data is in linked files.
Some files don't even contain the track list, only chapter information.
mpv refused to play these, because normally, the main file dictates the
track layout.
Fix this by using the first segment for track data if no part of the
timeline is sourced from the main file.
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
Move most code from demux_mkv_fill_buffer() to read_next_block(). The
former is supposed to read raw blocks, while ..fill_buffer() reads
blocks and turns them into packets.
Somehow this was setup such that a BlockGroup can be incrementally
read (at least in theory). This makes no sense, as BlockGroup can
contain only one Block (despite its name). There's no need to read
this incrementally, and makes the code confusing for no gain.
Read all the BlockGroup sub-elements with a single function call,
without keeping global state for BlockGroup parsing.
The code for reading block data was duplicated. Move it into a function.
Instead of returning on error (possibly due to corrupt data) and
signalling EOF, continue by trying to find the next block. This makes
error handling slightly simpler too, because you don't have to care
about freeing the current block. We could still signal EOF in this case,
but trying to resync sounds better for dealing with corrupted files.
Matroska files prepared for streaming have clusters with unknown size.
These files are pretty rare, see e.g. test4.mkv from the official
Matroska test file collection.
The end positions of the current cluster and block were managed by
tracking their size and how much of them were read, instead of just
using the absolute end positions.
I'm not sure about the reasons why this code was originally written
this way. One obvious concern is reading from pipes and such, but the
stream layers hides this. stream_tell(s) works even when reading from
pipes. It's also a fast call, and doesn't involve the stream
implementation or syscalls. Keeping track of the cluster/block end is
simpler and there's no reason why this wouldn't work.
Incomplete files don't have a valid index, because the index is usually
located near the end of a file. In this case, an index is created on the
fly during demuxing, or when seeks are done.
This used a completely different code path, which leads to unnecessary
complications and code duplication. Use the normal index data structure
instead. The seeking code at the end of seek_creating_index() (in this
commit renamed to create_index_until()) is removed. The normal seek code
does the same thing instead.