Run opening the stream and opening the demuxer in a separate thread.
This should remove the last code paths in which the player can normally
get blocked on network.
When the stream is opened, the player will still react to input and so
on. Commands to abort opening can also be handled properly, instead of
using some of the old hacks in input.c. The only thing the user can
really do is aborting loading by navigating the playlist or quitting.
Whether playback abort works depends on the stream implementation; with
normal network, this will depend on what libavformat (via "interrupt"
callback) does.
Some pain is caused by DVD/BD/DVB. These want to reload the demuxer
sometimes. DVB wants it in order to discard old, inactive streams.
DVD/BD for the same reason, and also for reloading stream languages
and similar metadata. This means the stream and the demuxer have to
be loaded separately.
One minor detail is that we now need to copy all global options. This
wasn't really needed before, because the options were accessed on
opening only, but since opening is now on a separate thread, this
obviously becomes a necessity.
Continues commit 348dfd93. Replace other places where input was manually
fetched with common code.
demux_was_interrupted() was a weird function; I'm not entirely sure
about its original purpose, but now we can just replace it with simpler
code as well. One difference is that we always look at the command
queue, rather than just when cache initialization failed. Also, instead
of discarding all but quit/playlist commands (aka abort command), run
all commands. This could possibly lead to unwanted side-effects, like
just ignoring commands that have no effect (consider pressing 'f' for
fullscreen right on start: since the window is not created yet, it would
get discarded). But playlist navigation still works as intended, and
some if not all these problems already existed before that in some
forms, so it should be ok.
Apparently users prefer this behavior.
It was used for subtitles too, so move the code to calculate the video
offset into a separate function. Seeking also needs to be fixed.
Fixes#1018.
The VO is run inside its own thread. It also does most of video timing.
The playloop hands the image data and a realtime timestamp to the VO,
and the VO does the rest.
In particular, this allows the playloop to do other things, instead of
blocking for video redraw. But if anything accesses the VO during video
timing, it will block.
This also fixes vo_sdl.c event handling; but that is only a side-effect,
since reimplementing the broken way would require more effort.
Also drop --softsleep. In theory, this option helps if the kernel's
sleeping mechanism is too inaccurate for video timing. In practice, I
haven't ever encountered a situation where it helps, and it just burns
CPU cycles. On the other hand it's probably actively harmful, because
it prevents the libavcodec decoder threads from doing real work.
Side note:
Originally, I intended that multiple frames can be queued to the VO. But
this is not done, due to problems with OSD and other certain features.
OSD in particular is simply designed in a way that it can be neither
timed nor copied, so you do have to render it into the video frame
before you can draw the next frame. (Subtitles have no such restriction.
sd_lavc was even updated to fix this.) It seems the right solution to
queuing multiple VO frames is rendering on VO-backed framebuffers, like
vo_vdpau.c does. This requires VO driver support, and is out of scope
of this commit.
As consequence, the VO has a queue size of 1. The existing video queue
is just needed to compute frame duration, and will be moved out in the
next commit.
If you for example use --audio-file, disable the external track, seek,
and enable the external track again, the playback position of the
external file was off, and you would get major A/V desync. This was
actually supposed to work, but broke at some time ago (probably commit
2b87415f). It didn't work, because it attempted to seek the stream if it
was already selected, which was always true due to
reselect_demux_streams() being called before that.
Fix by putting the initial selection and the seek together.
This adds a thread to the demuxer which reads packets asynchronously.
It will do so until a configurable minimum packet queue size is
reached. (See options.rst additions.)
For now, the thread is disabled by default. There are some corner cases
that have to be fixed, such as fixing cache behavior with webradios.
Note that most interaction with the demuxer is still blocking, so if
e.g. network dies, the player will still freeze. But this change will
make it possible to remove most causes for freezing.
Most of the new code in demux.c actually consists of weird caches to
compensate for thread-safety issues (with the previously single-threaded
design), or to avoid blocking by having to wait on the demuxer thread.
Most of the changes in the player are due to the fact that we must not
access the source stream directly. the demuxer thread already accesses
it, and the stream stuff is not thread-safe.
For timeline stuff (like ordered chapters), we enable the thread for the
current segment only. We also clear its packet queue on seek, so that
the remaining (unconsumed) readahead buffer doesn't waste memory.
Keep in mind that insane subtitles (such as ASS typesetting muxed into
mkv files) will practically disable the readahead, because the total
queue size is considered when checking whether the minimum queue size
was reached.
Stop using it in most places, and prefer STREAM_CTRL_GET_SIZE. The
advantage is that always the correct size will be used. There can be no
doubt anymore whether the end_pos value is outdated (as it happens often
with files that are being downloaded).
Some streams still use end_pos. They don't change size, and it's easier
to emulate STREAM_CTRL_GET_SIZE using end_pos, instead of adding a
STREAM_CTRL_GET_SIZE implementation to these streams.
Make sure int64_t is always used for STREAM_CTRL_GET_SIZE (it was
uint64_t before).
Remove the seek flags mess, and replace them with a seekable flag. Every
stream must set it consistently now, and an assertion in stream.c checks
this. Don't distinguish between streams that can only be forward or
backwards seeked, since we have no such stream types.
stream.start_pos was needed for optical media only, and (apparently) not
for very good reasons. Just get rid of it.
For stream_dvd, we don't need to do anything. Byte seeking was already
removed from it earlier.
For stream_cdda and stream_vcd, emulate the start_pos by offsetting the
stream pos as seen by the rest of mpv.
The bits in discnav.c and loadfile.c were for dealing with the code
seeking back to the start in demux.c. Handle this differently by
assuming the demuxer is always initialized with the stream at start
position, and instead seek back if initializing the demuxer fails.
Remove the --sb option, which worked by modifying stream.start_pos. If
someone really wants this option, it could be added back by creating a
"slice" stream (actually ffmpeg already has such a thing).
And consistently use MP_NOPTS_VALUE as error value for the users of this
function. This is better than using -1, especially because negative
values can be valid timestamps.
The terminal OSD code includes the handling of the terminal status line,
showing player OSD messages on the terminal, and showing subtitles on
terminal (the latter two only if there is no video window, or if
terminal OSD is forced).
This didn't handle some corner cases correctly. For example, showing an
OSD message on the terminal always cleared the previous line, even if
the line was an important message (or even just the command prompt, if
most other messages were silenced).
Attempt to handle this correctly by keeping track of how many lines the
terminal OSD currently consists of. Since there could be race conditions
with other messages being printed, implement this in msg.c. Now msg.c
expects that MSGL_STATUS messages rewrite the status line, so the caller
is forced to use a single mp_msg() call to set the status line.
Instead of littering print_status() all over the place, update the
status only once per playloop iteration in update_osd_msg(). In audio-
only mode, the status line might now be a little bit off, but it's
perhaps ok.
Print the status line only if it has changed, or if another message was
printed. This might help with extremely slow terminals, although in
audio+video mode, it'll still be updated very often (A-V sync display
changes on every frame).
Instead of hardcoding the terminal sequences, use
terminfo/termcap to get the sequences. Remove the --term-osd-esc option,
which allowed to override the hardcoded escapes - it's useless now.
The fallback for terminals with no escape sequences for moving the
cursor and clearing a line is removed. This somewhat breaks status line
display on these terminals, including the MS Windows console: instead of
querying the terminal size and clearing the line manually by padding the
output with spaces, the line is simply not cleared. I don't expect this
to be a problem on UNIX, and on MS Windows we could emulate escape
sequences. Note that terminal OSD (other than the status line) was
broken anyway on these terminals.
In osd.c, the function get_term_width() is not used anymore, so remove
it. To remind us that the MS Windows console apparently adds a line
break when writint the last column, adjust screen_width in terminal-
win.c accordingly.
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.
Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.