Reduce the default tolerance for timestamp jumps from 60 to 15 seconds.
For .ts files, where ts_resets_possible coming from AVFMT_TS_DISCONT is
set, apply a more sophisticated heuristic. It's clear that such a file
wouldn't have a framerate below, say, 23hz. If the demuxer reports a
lower fps, we allow longer PTS jumps.
This should replace long pauses on discontinuities with .ts files with
at most a short stutter.
Of course, all kinds of things could go wrong anyway if the source is
VFR, or FFmpeg's frame rate detection fails in some other way. I haven't
found such a file yet, though.
Fixes PNG cover art not showing up immediately (for example when running
with --pause).
libavformat exports embedded cover art as a single packet. For example,
a PNG attachment simply contains the PNG image, which can be sent to the
decoder. Normally you would expect that the PNG decoder would return 1
frame for 1 packet, without any delays. But this stopped working, and it
incurs a 1 frame delay.
This is perfectly legal (even if unexpected), so let our code feed the
decoder packets until we get something back. (In theory feeding the
packet instead of a real flush packet is still somewhat questionable.)
last_av_difference can be MP_NOPTS_VALUE under certain circumstances
(like no video timestamp yet). This triggered the desync message,
because fabs(MP_NOPTS_VALUE) is quite a large value. We don't want to
show a message in this situation.
libavcodec makes it impossible to distinguish dropped frames (requested
with AVCodecContext.skip_frame), and cases when the decoder simply does
not return a frame by default (such as with VP9, which has invisible
reference frames).
This confuses users when decoding VP9 video. It's basically a cosmetic
issue, so just paint it over by ignoring them if framedropping is
disabled.
When playing cover art, it conceptually reaches EOF as soon as the image
was put on the VO, causing the EOF message to be repeated every time new
audio was decoded. Just silence the message.
Use OPT_CHOICE_C() instead of the custom parser. The functionality is
pretty much equivalent.
(On a side note, it seems --video-stereo-mode can't be removed, because
it controls whether to "reduce" stereo video to mono, which is also the
default. In fact I'm not sure how this should be handled at all.)
"Non-monotonic" isn't even 100% correct; it's missing "strictly" (for
briefness I guess), and also the message is printed if the PTS jumps
forward. So just print something that is likely a bit easier to
understand.
For some reason there were two points in the code where it warned
against non-monotonic video PTS. The one in video.c triggered on PTS
going backwards or making large jumps forwards, while dec_video.c
triggered on PTS going backwards or PTS not changing. Merge them into a
single check, which warns against all cases.
Broken drivers are an issue rather often. Maybe this gives the user an
idea that this could be the reason. (We can't dump much more info on a
80x24 terminal.)
In ancient times, this was needed because it was not default, and many
VOs had problems with it. But it was always default in mpv, and all VOs
are required to deal with it. Also, running --fixed-vo=no is not useful
and just creates weird corner cases. Get rid of it.
This reverts commit 7b3feecbc2.
It's broken, hr-seek never ends at a video position before seek pts.
Not sure what I was thinking, although it did work anyway when
artificially forcing a video frame to display before seek pts.
At least there is _some_ problem if this happens. It would mean that
audio is playing slower than video. Normally, video is synced to audio,
so if audio stops playback completely, video will not advance at all.
But using things like --autosync, it's well possible that this kind of
desync happens.
Move the update_avsync_before_frame() call further down. Moving it
closer to where the time_frame value is used (and which the function
updates) should make the code more readable. With this change, there's
no need anymore to reset the time_frame value on the video reconfig
path.
Move the update_avsync_after_frame() up. Now no meaningful amount of
time passes since the previous get_relative_time() call anymore, and the
second one can be removed.
mpctx->audio_delay always has the same value as opts->audio_delay. (This
was not the case a long time ago, when the audio-delay property didn't
actually write to opts->audio_delay. I think.)
This allows seeking audio between two video frames that are relatively
far away.
The implementation of this is a bit subtle. It pretend the audio
position is different, and the actual PTS adjustment happens in audio.c
with this line:
sync_pts -= mpctx->audio_delay - mpctx->delay;
Effectively this is the same as setting sync_pts to hrseek_pts after
this line, though. (I'm actually not sure if this could be written in a
more straightforward way; probably yes.)
We still need to send the VO a duration in these cases. Disabling
framedrop has logically absolutely nothing to do with these cases; it
was overlooked in commit 918b06c4.
So we always send the frame duration (or a guess for it), and check
whether framedropping is actually enabled in the VO code. (It would
be cleaner to send framedrop as a flag, but I don't care about that
right now.)
The last video frame is another case that has a separate code path,
although it's pretty similar to the one in commit 73e5aa87. Fix this
in a different way, which also takes care of the last frame case,
although without context the code becomes slightly more tricky.
As further cleanup, move the decision about framedropping itself to
the same place, so the check in vo.c becomes much simpler. The check
for the vo->driver->encode flag, which is remvoed completely, was
redundant too.
Fixes#1480.
If the video format changes (e.g. different frame size), a special code
path is entered to wait until the currently displayed frame is done.
Otherwise, the frame before the change would be destroyed by the
vo_reconfig() call.
This code path didn't respect --untimed; correct this.
Fixes#1475.
There are currently 568 pixel formats (actually fewer, but the namespace
is this big), and for each format elaborate synchronization was done to
call it synchronously on the VO. This is completely unnecessary, and we
can do with just a single call.
This is basically a hack; but apparently a needed one, since many
vapoursynth filters insist on having a FPS set.
We need to apply the FPS override before creating the filters. Also
change some terminal output related to the FPS value.
Most of this is explained in the code comments. This change should
improve performance with vapoursynth, especially if concurrent requests
are used.
This should change nothing if vf_vapoursynth is not in the filter chain,
since non-threaded filters obviously can not asynchronously finish
filtering of frames.
This adds API to libmpv that lets host applications use the mpv opengl
renderer. This is a more flexible (and possibly more portable) option to
foreign window embedding (via --wid).
This assumes that methods like context sharing and multithreaded OpenGL
rendering are infeasible, and that a way is needed to integrate it with
an application that uses a single thread to render everything.
Add an example that does this with QtQuick/qml. The example is
relatively lazy, but still shows how relatively simple the integration
is. The FBO indirection could probably be avoided, but would require
more work (and would probably lead to worse QtQuick integration, because
it would have to ignore transformations like rotation).
Because this makes mpv directly use the host application's OpenGL
context, there is no platform specific code involved in mpv, except
for hw decoding interop.
main.qml is derived from some Qt example.
The following things are still missing:
- a way to do better video timing
- expose GL renderer options, allow changing them at runtime
- support for color equalizer controls
- support for screenshots
It feels strange that seeking past EOF with --keep-open actually leaves
the player at a random position. You can't even unpause, because the
demuxer is in the EOF state, and what you see on screen is just what was
around before the seek.
Improve this by attempting to seek to the last video frame if EOF
happens. We explicitly don't do this if EOF was reached normally to
increase robustness (if the VO got a frame since the last seek, it
obviously means we had normal playback before EOF).
If an error happens when trying to find the last frame (such as not
actually finding a last frame because e.g. the demuxer misbehaves), this
will probably turn your CPU into a heater. There is no logic to prevent
reinitiating the last-frame search if the last-frame search reached EOF.
(Pausing usually prevents that EOF is reached again after a successful
last-frame search.)
Fixes#819.
In all of these situations, NULL is logically not allowed, making the
checks redundant.
Coverity complained about accessing the pointers before checking them
for NULL later.
This was shown only if decoder-framedropping was enabled, and only if at
least 50 frames were dropped by it. Since drop_frame_cnt used to mean
"number of late frames", this code made sense, but this is not the case
anymore: drop_frame_cnt can be even 0, all while video gets hopelessly
behind audio.
One problem with this is that short desync spikes (which usually can
probably dealt with) will also cause this message to be shown. If it
gets triggered too often, the code will need to be adjusted.
The player was supposed to exit playback if both video and audio failed
to initialize (or if one of the streams was not selected when the other
stream failed). This didn't work; for one this check was missing from
one of the failure paths. And more importantly, both checked the
current_track array incorrectly.
Fix these issues, and move the failure handling code into a common
function.
CC: @mpv-player/stable
This could produce an extra frame, because reaching the maximum merely
signals the playloop to exit, without strictly enforcing the limit.
Fixes#1181.
CC: @mpv-player/stable
For cover art, we pretend that the video stream is infinite, but also
stop decoding once we have an image on the VO (this seems advantageous
for the case when strange filters are inserted or the VO image gets
lost). Since a while ago, the video chain started decoding 2 images
though ("Non-monotonic video pts: 0.000000 <= 0.000000"), which is
annoying and wasteful.
Improve this by handling a certain corner case at initialization, which
will decode a second image while the first one is still stuck in the
filter chain. Also, just in case there are filters which buffer a lot,
also force EOF filtering (which means we tell the filters to flush
buffered frames).
CC: @mpv-player/stable
Each subsystem (or similar thing) had an INITIALIZED_ flag assigned. The
main use of this was that you could pass a bitmask of these flags to
uninit_player(). Except in some situations where you wanted to
uninitialize nearly everything, this wasn't really useful. Moreover, it
was quite annoying that subsystems had most of the code in a specific
file, but the uninit code in loadfile.c (because that's where
uninit_player() was implemented).
Simplify all this. Remove the flags; e.g. instead of testing for the
INITIALIZED_AO flag, test whether mpctx->ao is set. Move uninit code
to separate functions, e.g. uninit_audio_out().
The messages "Audio: no audio" and "Video: no video" could be printed
twice each if initializing them failed. Prevent his silliness.
CC: @mpv-player/stable
We inserted these filters with fixed parameters, which was ok. But this
also didn't change image parameters for the filters down the filter
chain and the VO. For example, if rotation by 90° was requested by the
file, we would insert a filter and rotate the video, but the VO would
still receive image parameters that direct rotation by 90°.
This wasn't a problem, but it could become one.
Fix this by letting the filters automatically pick up the image params.
The image params are reset on application. (We could probably also
always try to apply and reset image params in a filter, instead of
having special "auto" parameters. This would probably work, and video.c
would insert a "rotate=0" filter. But I'm afraid this would be confusing
and the current solution is cosmetically slightly nicer.)
Unfortunately, the vf_stereo3d.c change turned out a big mess, but once
the "internal" filter is fully replaced with libavfilter, most of this
can be radically simplified.
There's no need to update OSD messages and the terminal status if nobody
is going to see it. Since the player doesn't block on video display
anymore, this update happens to often and probably burns slightly more
CPU than necessary. (OSD redrawing is handled separately, so it's just
mostly useless text processing and such.)
Change it so that it's updated only on every video frame or all 50ms
(whatever comes first).
For VO OSD, we could in theory try to lock to the OSD redraw heuristic
or the display refresh rate, but that's more complicated and doesn't
work for the terminal status.
We generally want 2 things:
1. minimal wakeups for decoding each frame
2. minimal number of frames decoded on continuous seeking
Commit 35810cb8 changed this a bit, and fixed 1. But it broke 2., and
now it decodes 2 frames instead of 1 when you keep seeking (arrow key
held down or such). This made seeking appear slower.
Fix this by making the logic more explicit. In particular, call the
filters only if we actually try to get a new frame.
When playing with --no-audio and all other distractions disabled (like
OSC), it still wakes up 2 times per frame - but the second time is
merely because the VO didn't accept the new frame yet.
Normally, feeding a packet to the decoder should always return a frame
_if_ we received a frame before. So while we can't know exactly whether
a frame was dropped, at least the normal case is easily detectable.
This means we display something closer to the actual framedrop count,
instead of a bad guess.
This is the "old" framedropping mode (derived from MPlayer). At least in
the mplayer2/mpv source base, it stopped working properly years ago (or
maybe it never worked properly). For one, it depends on the video
framerate, which assume constant framerate. Another problem was that it
could lead to freezing video display: video could get so much behind
that it couldn't recover from framedrop.
Make some small changes to improve this.
Don't use the current audio position to check how much we are behind.
Instead, use the last known A/V difference. last_av_difference is
updated only when a video frame is scheduled for display. This means we
can keep stop dropping once we're done catching up, even if video is
technically still behind. What helps us here that this forces a video
frame to be displayed after a while. Likewise, we reset the
dropped_frames count only when scheduling a new frame for display as
well.
Some inspiration was taken from earlier work by xnor (see issue #620),
although the implementation turned out quite different.
This still uses the demuxer-reported (possibly broken) FPS value. It
also doesn't account for filters changing FPS. We can't do much about
this, because without decoding _and_ filtering, we just can't know how
long a frame is. In theory, you could derive that from the raw packet
timestamps and the filter chain contents, but actually doing this is
too involved. Fortunately, the main thing the FPS affects is actually
the displayed framedrop count.
Rename video_decode_and_filter to video_filter, and add a new
video_decode_and_filter function. This function now calls the decoder.
This is done so that we can check filters a second time after decoding,
which avoids a useless playloop iteration.
(This and the previous commits are really just microoptimizations, which
simply reduce the number of times the playloop has to recheck
everything.)
Move the check to a function. Run the check a second time after
decoding/filtering. This second check is strictly speaking redundant
(which is why it wasn't done until now), but it avoids a useless
playloop iteration.
Move this code below the code that "shifts" the newly filtered frame.
This allows us to skip a useless playloop iteration later, because
obviously we need to filter a new frame after the previous frame has
been "shifted", and not before that.
This inserts an automatic conversion filter if a Matroska file is marked
as 3D (StereoMode element). The basic idea is similar to video rotation
and colorspace handling: the 3D mode is added as a property to the video
params. Depending on this property, a video filter can be inserted.
As of this commit, extending mp_image_params is actually completely
unnecessary - but the idea is that it will make it easier to integrate
with VOs supporting stereo 3D mogrification. Although vo_opengl does
support some stereo rendering, it didn't support the mode my sample file
used, so I'll leave that part for later.
Not that most mappings from Matroska mode to vf_stereo3d mode are
probably wrong, and some are missing.
Assuming that Matroska modes, and vf_stereo3d in modes, and out modes
are all the same might be an oversimplification - we'll see.
See issue #1045.
This shouldn't change anything functionally.
Change the A/V desync message. --framedrop is enabled by default now, so
the text must be changed a little. I've never heard of audio outputs
messing up A/V sync recently, so remove that part.
Remove the unused ao_pts field.
Reorder 2 A/V sync related expressions so that they look the same.
Commit 846257da introduced an accidental feature: if you kept seeking
(so playback never really resumes), the audio would never be played.
This was nice, but commit 4c25b000 accidentally removed it again (due
to the video_next_pts being earlier available than it used to be, so
audio could be played before the player executed the next queued seek).
Implicitly reintroduce the old behavior again by not decoding a second
video frame immediately. Usually, the second frame is used to compute
the frame duration needed to for accurate framedropping, but since the
first frame after a seek is never dropped, we don't need this.
Now the video code will queue the new frame to the VO immediately, and
since fill_audio_out_buffers() is called in the playloop before
write_video() and execute_queued_seek(), it never gets the chance to
enter STATUS_READY, and seeks will be silent.
This also has a nice side-effect: since the second frame is not decoded
and filtered, seeking becomes slightly faster (back to the same level
as with framedrop disabled).
It seems this still sometimes plays a period of audio when keeping a
seek key down. In my tests, this appeared to happen because the seek
finished before the next key repeat was sent.
Commit 5afc025c broke this. The reason is that mpctx->delay is updated
when a new video frame is added. This value is also needed to resync
audio, but it will be for the wrong PTS. They must be consistent with
each other, and if they aren't, initial sync will be off by N video
frames, which results at least in worse user experience.
This can be reproduced by for example heavily switching between normal
and 2x speed, or similar.
Fix by readding the video_next_pts field (keeping its use minimal,
instead of reverting the commit that removed it).
This simplifies the code, and fixes an odd bug: the second-last frame
was displayed for a very short duration if framedrop was enabled. The
reason was that basically the time difference between second-last and
last frame were skipped, because at this point EOF was already
signaled. Also see commit b0959488 for a similar issue in the
same code.
This removes the messiness of the next_frame 2-frame queue, and
strictly runs the "new frame" code when a frame is moved to the first
position of the queue, instead of somehow messing with return codes.
This also merges update_video() into video_output_image().
No functional changes. init_vo() is now needed a bit further down, and
moving it keeps definition and use close. adjust_sync() will be used by
a function further up in one of the following commits.
This mostly uses the same idea as with vo_vdpau.c, but much simplified.
On X11, it tries to get the display framerate with XF86VM, and limits
the frequency of new video frames against it. Note that this is an old
extension, and is confirmed not to work correctly with multi-monitor
setups. But we're using it because it was already around (it is also
used by vo_vdpau).
This attempts to predict the next vsync event by using the time of the
last frame and the display FPS. Even if that goes completely wrong,
the results are still relatively good.
On other systems, or if the X11 code doesn't return a display FPS, a
framerate of 1000 is assumed. This is infinite for all practical
purposes, and means that only frames which are definitely too late are
dropped. This probably has worse results, but is still useful.
"--framedrop=yes" is basically replaced with "--framedrop=decoder". The
old framedropping mode is kept around, and should perhaps be improved.
Dropping on the decoder level is still useful if decoding itself is too
slow.
This ran adjust_sync() on every playloop iteration, instead of every
newly decoded frame. It seems this was idempotent in the common case,
but the code was originally designed to be run once only, so restore
that.
The previous commit broke these things, and fixing them is separate in
this commit in order to reduce the volume of changes.
Move the image queue from the VO to the playback core. The image queue
is a remnant of the old way how vdpau was implemented, and increasingly
became more and more an artifact. In the end, it did only one thing:
computing the duration of the current frame. This was done by taking the
PTS difference between the current and the future frame. We keep this,
but by moving it out of the VO, we don't have to special-case format
changes anymore. This simplifies the code a lot.
Since we need the queue to compute the duration only, a queue size
larger than 2 makes no sense, and we can hardcode that.
Also change how the last frame is handled. The last frame is a bit of a
problem, because video timing works by showing one frame after another,
which makes it a special case. Make the VO provide a function to notify
us when the frame is done, instead. The frame duration is used for that.
This is not perfect. For example, changing playback speed during the
last frame doesn't update the end time. Pausing will not stop the clock
that times the last frame. But I don't think this matters for such a
corner case.
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.
The function video_decode_and_filter(), called between initializing the
local vf variable and using it, can actually destroy and recreate the
filter. Thus, the vf variable turns into a dangling pointer if that
happens.
Could be observed with: --hwdec=vda --deinterlace=yes --vf=yadif
(Also happens with vdpau/vaapi.)
Completely useless, and could accidentally be enabled by cycling
framedrop modes. Just get rid of it.
But still allow triggering the old code with --vd-lavc-framedrop, in
case someone asks for it. If nobody does, this new option will be
removed eventually.
If this code is not skipped, encoding (or dumping with --ao=pcm) will
attempt to adjust video timing to audio. Since another commit (0cce8fe6)
already avoids writing audio ahead, this didn't slow down encoding to
realtime, but it was still significantly slower.
This change should actually remove all extra sleeping.
Handle --term-playing-msg at a better place.
Move MPV_EVENT_TICK hack into a separate function. Also add some words
to the client API that you shouldn't use it. (But better leave breaking
it for later.)
Handle --frames and frame_step differently. Remove the mess from the
playloop, and do it after frame display. Give up on the weird semantics
for audio-only mode (they didn't make sense anyway), and adjust the
manpage accordingly.
Playing audio files with embedded cover art broke due to some of the
recent changes. Treat video EOF properly, and don't burn the CPU.
Disable hrseek for video in attached picture mode, since the decoder
will always produce a new image, which makes hrseek never terminate.
Fixes#970.
Basically move the code from playloop.c to video.c. The new function
write_video() now contains the code that was part of run_playloop().
There are no functional changes, except handling "new_frame_shown"
slightly differently. This is done so that we don't need new a new
MPContext field or a return value for write_video() to signal this
condition. Instead, it's handled indirectly.
This also reduces some code duplication with other parts of the code.
The changfe is mostly cosmetic, although there are also some subtle
changes in behavior. At least one change is that the big desync message
is now printed after every seek.
Frames buffered in filters weren't flushed, so on EOF, the last frames
were dropped, depending on how much filters buffered. Oops.
Test case: "mpv something.jpg --vf=buffer"
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 commit makes audio decoding non-blocking. If e.g. the network is
too slow the playloop will just go to sleep, instead of blocking until
enough data is available.
For video, this was already done with commit 7083f88c. For audio, it's
unfortunately much more complicated, because the audio decoder was used
in a blocking manner. Large changes are required to get around this.
The whole playback restart mechanism must be turned into a statemachine,
especially since it has close interactions with video restart. Lots of
video code is thus also changed.
(For the record, I don't think switching this code to threads would
make this conceptually easier: the code would still have to deal with
external input while blocked, so these in-between states do get visible
[and thus need to be handled] anyway. On the other hand, it certainly
should be possible to modularize this code a bit better.)
This will probably cause a bunch of regressions.
The video flushing logic was broken: if there are no more packets,
decode_image() will feed flush packets to the decoder. Even if an image
was produced, it will return the demuxer EOF state, and since commit
7083f88c, this EOF state is returned to the caller, which is incorrect.
Revert this part of the change, and explicitly check for VD_WAIT (the
bogus change was intended to forward this error code to the caller).
Also, turn the "r < 1" into something equivalent that doesn't rely on
the exact value of VD_EOF. "r < 0" is ok, because at least here, errors
are always negative.
In my opinion this is not really necessary, since there's only a single
user of update_video(), but others reading this code would probably hate
me for using magic integer values instead of symbolic constants.
This should be a purely cosmetic commit; any changes in behavior are
bugs.
Instead of blocking on the demuxer when reading a packet, let packets be
read asynchronously. Basically, it polls whether a packet is available,
and if not, the playloop goes to sleep until the demuxer thread wakes it
up.
Note that the player will still block for I/O, because audio is still
read synchronously. It's much harder to do the same change for audio
(because of the design of the audio decoding path and especially
initialization), so audio will have to be done later.
DVD and Bluray (and to some extent cdda) require awful hacks all over
the codebase to make them work. The main reason is that they act like
container, but are entirely implemented on the stream layer. The raw
mpeg data resulting from these streams must be "extended" with the
container-like metadata transported via STREAM_CTRLs. The result were
hacks all over demux.c and some higher-level parts.
Add a "disc" pseudo-demuxer, and move all these hacks and special-cases
to it.
Let the VOs draw the OSD on their own, instead of making OSD drawing a
separate VO driver call. Further, let it be the VOs responsibility to
request subtitles with the correct PTS. We also basically allow the VO
to request OSD/subtitles at any time.
OSX changes untested.
vo_vdpau currently has a video queue larger than 1 entry, which causes
the video display code to never queue display the video frame. This is
because we consider cover art an endless stream of frames decoded from
the same source packet, and include special logic to actually only
decode and display 1 frame.
Also, make decode_image() also signal EOF in the cover art case.
When the player is paused, and video filters are changed, an exact seek
is executed to refresh the display. Increase the exactness of the seek
in this case; this reuses the code used for frame backstepping.
It might help in cases where seeking is very imprecise, such as with
transport streams.
This allows disabling of decoder framedrop during hr-seek.
It's basically another useless option, but it will help exploring
whether this framedropping really makes seeking faster, or whether
disabling it helps with precise seeking (especially frame backstepping).
Until recently, the VO was an unavoidable part of the seeking code path.
This was because vdpau deinterlacing could double the framerate, and hr-
seek and framestepping etc. all had to "see" the additional frames. But
we've removed the frame doubling from the vdpau VO and moved it into a
video filter (vf_vdpaupp), and there's no reason left why the VO should
participate in seeking.
Instead of queuing frames to the VO during seek and skipping them
afterwards, drop the frames early.
This actually might make seeking with vo_vdpau and software decoding
faster, although I haven't measured it.
Now we avoid calling update_video() twice on reconfig (once to check
whether there are still new frames, and again to actually do the
reconfig). Instead, we check whether there's still something going on
before calling update_video() at all, and depending on that
update_video() will be allowed to reconfig or not.
This will simplify some things later.
When loading a video, and a script reacts to MPV_EVENT_VIDEO_RECONFIG,
and the script inserts a video filter, the first frame can be skipped.
This happens simply because the first frame is (usually) still queued in
the video filter chain, and changing the filter chain will drop all
queued frames. So this is just a corner case that just happens in a
weird situation.
But it's still annoying when having such a script, and starting
something where the first frame is very visible, and not starting in
paused mode. (All in all, a corner case.) Do this by immediately queuing
1 filtered frame to the VO immediately after reconfig, instead of
leaving it to the video loop doing it as "incremental" work. Simply
fallthrough to the next case. We must not overwrite "r" in this case,
because that contains the current status.
Note that the first frame will not be filtered using the inserted
filter.
Apparently the value of a pointer is "indeterminate" after a free()
call, even if you never dereference the pointer after the free. Since
talloc_free() calls free(), this applies here.
Change how the video decoding loop works. The structure should now be a
bit easier to follow. The interactions on format changes are (probably)
simpler. This also aligns the decoding loop with future planned changes,
such as moving various things to separate threads.
Or in other words, add support for properly draining remaining frames
from video filters. vf_yadif is buffering at least one frame, and the
buffered frame was not retrieved on EOF.
For most filters, ignore this for now, and just adjust them to the
changed semantics of filter_ext. But for vf_lavfi (used by vf_yadif),
real support is implemented. libavfilter handles this simply by passing
a NULL frame to av_buffersrc_add_frame(), so we just have to make
mp_to_av() handle NULL arguments.
In load_next_vo_frame(), we first try to output a frame buffered in the
VO, then the filter, and then (if EOF is reached and there's still no
new frame) the VO again, with draining enabled. I guess this was
implemented slightly incorrectly before, because the filter chain still
could have had remaining output frames.
If the VO can't do rotation, insert a filter to do this. Note that this
doesn't reuse the filter insertion code from command.c (used by "vf"
input command), because that would end up more complicated: we don't
even want to change the user filter option.
We want to move the AO to its own thread. There's no technical reason
for making the ao struct opaque to do this. But it helps us sleep at
night, because we can control access to shared state better.
The code removed from handle_input_and_seek_coalesce() did two things:
1. If there's a queued seek, stop accepting non-seek commands, and delay
them to the next playloop iteration.
2. If a seek is executing (i.e. the seek was unqueued, and now it's
trying to decode and display the first video frame), stop accepting
seek commands (and in fact all commands that were queued after the
first seek command). This logic is disabled if seeking started longer
than 300ms ago. (To avoid starvation.)
I'm not sure why 1. would be needed. It's still possible that a command
immediately executed after a seek command sees a "seeking in progress"
state, because it affects queued seeks only, and not seeks in progress.
Drop this code, since it can easily lead to input starvation, and I'm
not aware of any disadvantages.
The logic in 2. is good to make seeking behave much better, as it
guarantees that the video display is updated frequently. Keep the core
idea, but implement it differently. Now this logic is applied to seeks
only. Commands after the seek can execute freely, and like with 1., I
don't see a reason why they couldn't. However, in some cases, seeks are
supposed to be executed instantly, so queue_seek() needs an additional
parameter to signal the need for immediate update.
One nice thing is that commands like sub_seek automatically profit from
the seek delay logic. On the other hand, hitting chapter seek multiple
times still does not update the video on chapter boundaries (as it
should be).
Note that the main goal of this commit is actually simplification of the
input processing logic and to allow all commands to be executed
immediately.
Do two things:
1. add locking to struct osd_state
2. make struct osd_state opaque
While 1. is somewhat simple, 2. is quite horrible. Lots of code accesses
lots of osd_state (and osd_object) members. To make sure everything is
accessed synchronously, I prefer making osd_state opaque, even if it
means adding pretty dumb accessors.
All of this is meant to allow running VO in their own threads.
Eventually, VOs will request OSD on their own, which means osd_state
will be accessed from foreign threads.
This is relatively hacky, but it's Christmas, so it's ok. This does two
things: 1. allow selecting two subtitle tracks, and 2. include a hack
that renders the second subtitle always as toptitle. See manpage
additions how to use this.
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.