Commit Graph

125 Commits

Author SHA1 Message Date
wm4 8bf57b8192 player: fix idle mode event handling
Idle mode went to sleep too early, e.g. just pressing "ESC" did nothing,
until the next event happened. This was because it directly went to
sleep after processing commands. What we should do instead is rechecking
all state after processing commands, redraw OSD, and then go to sleep.
This also fixes some strange OSD-related behavior.

Also move some other code around to separate idle mode initialization
from the normal run loop.
2014-09-13 01:14:07 +02:00
wm4 28fc13977e terminal-unix: move to thread
Do terminal input with a thread, instead of using the central select()
loop. This also changes some details how SIGTERM is handled.

Part of my crusade against mp_input_add_fd().
2014-09-10 00:48:12 +02:00
wm4 e1e8b07cfa player: reset some VO state when video is terminated
Useful for idle mode or if video is switched off during playback, and
--force-window is used.
2014-09-09 01:23:10 +02:00
wm4 f5af596237 player: some more input refactoring
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.
2014-09-07 20:44:54 +02:00
wm4 348dfd93c4 player: minor refactoring
Expose the central event handling functions explicitly, so that other
parts of the player can use them.

No functional changes. Preparation for the next commit.
2014-09-06 16:57:46 +02:00
wm4 2da246b9f7 player: add --osd-playing-msg option 2014-09-02 00:12:52 +02:00
wm4 7d79cd57ff player: fix quit handling when seeking past EOF while paused
The player didn't quit when seeking past EOF in audio-only mode while
paused. The only case when we don't want to quit is when the last video
frame is displayed while paused.

This logic was probably broken a while ago, but I'm not exactly sure.

CC: @mpv-player/stable
2014-08-29 19:13:34 +02:00
wm4 fb1266c98b player: update cache state only if requested
Add a mechanism to the client API code, which allows the player core to
query whether a client API event is needed at all. Use it for the cache
update.

In this case, this is probably a pure microoptimization; but the
mechanism will be useful for other things too.
2014-08-28 17:49:09 +02:00
Ben Boeckel 9780ff9642 player: simplify chapter display name code
The display name is always recomputed, so we can always toss the input
name.
2014-08-28 12:02:41 +02:00
wm4 f8a1bd1253 player: dynamically change cache wait times
Remove the hardcoded wait time of 2 seconds. Instead, adjust the wait
time each time we unpause: if downloading the data took longer than its
estimated playback time, increase the amount of data we wait for. If
it's shorter, decrease it.

The +/- is supposed to avoid oscillating between two values if the
elapsed time and the wait time are similar. It's not sure if this
actually helps with anything, but it can't harm.
2014-08-27 23:24:55 +02:00
wm4 cb642e7c84 player: slightly better cache underrun detection
Use the "native" underrun detection, instead of guessing by a low cache
duration. The new underrun detection (which was added with the original
commit) might have the problem that it's easy for the playloop to miss
the underrun event. The underrun is actually not stored as state, so if
the demuxer thread adds a new packet before the playloop happens to see
the state, it's as if it never happened. On the other hand, this means
that network was fast enough, so it should be just fine.

Also, should it happen that we don't know the cached range (the
ts_duration < 0 case), just wait until the demuxer goes idle (i.e.
read_packet() decides to stop). This pretty much should affect broken or
unusual files only, and there might be various things that could go
wrong. But it's more robust in the normal case: this situation also
happens when no packets have been read yet, and we don't want to
consider this as reason to resume playback.
2014-08-27 23:12:49 +02:00
wm4 c7208319d3 player: better cache status on status line
The cache percentage was useless. It showed how much of the total stream
cache was in use, but since the cache size is something huge and
unrelated to the bitrate or network speed, the information content of
the percentage was rather low.

Replace this with printing the duration of the demuxer-cached data, and
the size of the stream cache in KB.

I'm not completely sure about the formatting; suggestions are welcome.
Note that it's not easy to know how much playback time the stream cache
covers, so it's always in bytes.
2014-08-27 23:12:47 +02:00
wm4 dad90f616d player: fix basic playback
The "buffering" logic was active even if the stream cache was disabled.
This is contrary to what the manpage says. It also breaks playback
because of another bug: the demuxer cache is smaller than 2 seconds,
and thus the resume condition never becomes true.

Explicitly run this code only if the stream cache is enabled. Also, fix
the underlying problem of the breakage, and resume when the demuxer
thread stops reading in any case, not just on EOF.

Broken by previous commit. Unbreaks playback of local files.
2014-08-27 10:59:22 +02:00
wm4 0b428e4482 player: redo how stream caching and pausing on low cache works
Add the --cache-secs option, which literally overrides the value of
--demuxer-readahead-secs if the stream cache is active. The default
value is very high (10 seconds), which means it can act as network
cache.

Remove the old behavior of trying to pause once the byte cache runs
low. Instead, do something similar wit the demuxer cache. The nice
thing is that we can guess how many seconds of video it has cached,
and we can make better decisions. But for now, apply a relatively
naive heuristic: if the cache is below 0.5 secs, pause, and wait
until at least 2 secs are available.

Note that due to timestamp reordering, the estimated cached duration
of video might be inaccurate, depending on the file format. If the
file format has DTS, it's easy, otherwise the duration will seemingly
jump back and forth.
2014-08-27 03:39:04 +02:00
wm4 3cc3dea915 player: fix weird behavior when framestepping over format changes
When video format changes, the frame before the frame with the new
format sets video_status briefly to STATUS_DRAINING. This caused the
code to handle the EOF case to kick in, which just pauses the player
when trying to step past the last frame. As a result, trying to
framestep over format changes resulted in pausing the player.

Fix by testing against the correct status.
2014-08-26 20:45:41 +02:00
wm4 21f52aeeba audio: minor improvements to timeline switching
In theory, timestamps can be negative, so we shouldn't just return -1
as special value.

Remove the separate code for clearing decode buffers; use the same code
that is used for normal seek reset.
2014-08-23 11:39:07 +02:00
wm4 005f592d54 player: some more debugging output 2014-08-22 16:25:55 +02:00
wm4 75005ec06d player: don't clobber playback position on video end
If video reaches EOF, and audio is also EOF (or is otherwise not
meaningful, like audio disabled), then the playback position was briefly
set to 0. Fix this by not trying to use a bogus audio PTS.

CC: @mpv-player/stable (maybe)
2014-08-22 14:22:06 +02:00
wm4 5afc025cc9 video: get rid of video_next_pts field
Not really needed anymore. Code should be mostly equivalent.

Also get rid of some other now-unused or outdated things.
2014-08-22 14:22:06 +02:00
wm4 7758c15e95 video: don't assume query_format is thread-safe
Although it's probably safe for most VOs, there's no guarantee.
2014-08-20 21:35:45 +02:00
wm4 9f31b73cda player: never print status messages before playback begins
After a new file is loaded, playback never starts instantly. Rather, it
takes some playloop iterations until initial audio and video have been
decoded, and the outputs have been (lazily) initialized. This means you
will get status line updates between the messages that inform of the
initialized outputs. This is a bit annoying and clutters the terminal
output needlessly.

Fix this by never printing the status line before playback isn't fully
initialized. Do this by reusing the --term-playing-msg code (which
prints a message once playback is initialized). This also makes sure the
status line _is_ shown during playback restart when doing seeks.

It's possible that the change will make the output more confusing if for
some reason is stuck forever initializing playback, but that seems like
an obscure corner case that never happens, so forget about it.
2014-08-18 01:25:59 +02:00
wm4 eb2924054f player: remove unneeded call
print_status() is called at a later point anyway (and before sleeping),
so this code has little effect. This code was added in commit a4f7a3df5,
and I can't observe any problems with idle mode anymore.

Now print_status() is called from a single place only, within osd.c.
2014-08-18 01:21:21 +02:00
wm4 14c1d864d9 player: cosmetics: make code more compact 2014-08-16 17:10:08 +02:00
wm4 543ba6c114 video: add VO framedropping mode
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.
2014-08-15 23:33:33 +02:00
wm4 fa7c421588 player: use virtual time for --audio-file with ordered chapters
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.
2014-08-15 23:32:37 +02:00
wm4 010b86fd34 player: don't quit with --loop-file
Fixes #1009.

CC: @mpv-player/stable
2014-08-13 21:50:01 +02:00
wm4 5ed7bc6321 video: fix and simplify video format changes and last frame display
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.
2014-08-12 23:24:08 +02:00
wm4 df58e82237 video: move display and timing to a separate thread
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.
2014-08-12 23:24:08 +02:00
wm4 ece61bfa10 player: don't delay OSD redraw when paused
We want this heuristic to trigger during normal playback only.
2014-08-10 13:24:29 +02:00
wm4 0f5aed9c62 player: some further playloop cleanups
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.
2014-08-03 20:31:00 +02:00
wm4 0ddbf92d06 player: make quit exit immediately
Stopping playback canceled waiting, but executed the remainder of the
playloop, including things like executing pointless seeks.
2014-08-03 20:30:39 +02:00
wm4 575314eafa player: allow redrawing screen during seeks
If seeks take very long, it's better not to freeze up the display.

(This doesn't handle the case when decoding video frames is extremely
slow; just if hr-seek is used, or the demuxer is threaded and blocks on
network I/O.)
2014-08-03 20:30:34 +02:00
wm4 33f465d9a7 player: don't ignore first chapter
It's a mystery why this was done this way. If the first chapter starts
later than the current position, we do have to return -1.
2014-07-31 22:54:57 +02:00
wm4 b4f24544bb client API: make "cache" property and similar observable
Achieve this by polling. Will be used by the OSC. Basically a bad hack -
but the point is that the mpv core itself is in the best position to
improve this later.
2014-07-31 04:19:41 +02:00
wm4 dacbaea1a8 player: rename a variable
Make it clear that this condition happens when switching to a new
timeline segment. It doesn't even need to coincide with a chapter.
2014-07-30 23:29:01 +02:00
wm4 1423bd0bfd player: move video display code out of the playloop
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.
2014-07-30 23:29:00 +02:00
wm4 8f2e9f1d61 player: split seek_reset()
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.
2014-07-30 23:29:00 +02:00
wm4 593ad996e0 player: fix time display wheen seeking past EOF with --keep-open
Regression since commit 261506e3. Internally speaking, playback was
often not properly terminated, and the main part of handle_keep_open()
was just executed once, instead of any time the user tries to seek. This
means playback_pts was not set, and the "current time" was determined by
the seek target PTS.

So fix this aspect of video EOF handling, and also remove the now
unnecessary eof_reached field.

The pause check before calling pause_player() is a lazy workaround for
a strange event feedback loop that happens on EOF with --keep-open.
2014-07-30 00:22:38 +02:00
wm4 b6a7c321db player: let explicitly imprecise seeks cancel precise seeks
If an imprecise seek is issues while a precise seek is ongoing,
don't wait up to 300ms (herustistic which usually improves user
experience), but instead let it cancel the seek.

Improves responsiveness of the OSC after the previous commit.

Note that we don't do this on "default-precise" seeks, because we
don't know if they're going to be precise or not.
2014-07-29 20:04:08 +02:00
wm4 6d15c491b0 player: remove a pointless field 2014-07-29 01:00:54 +02:00
wm4 25ceb3289d player: disable hr-seek in .ts files
Seeking in .ts files (and some other formats) is too unreliable, so
there's a separate code path for this case. But it breaks hr-seek.

Maybe hr-seek could actually be enabled in this case if we're careful
enough about timestamp resets, but for now nothing changes.
2014-07-29 00:59:00 +02:00
wm4 d6445d7ab6 player: allow precise seeking with percent seeks
I'm not sure why this was explicitly disabled. It's from mplayer2 times.
2014-07-29 00:26:52 +02:00
wm4 d563dc8cb9 player: update playback position on seek
If the actual PTS is not known yet right after a seek, the "time-pos"
property will just return the seek target PTS. For this purpose, trigger
a change event to make the client API update the "time-pos" and related
properties. (MPV_EVENT_TICK triggers this update.)
2014-07-29 00:20:54 +02:00
wm4 846257da13 player: logically speed up seek logic
Commit 261506e3 made constant seeking feel slower, because a subtle
change in the restart logic makes it now waste time showing another
video frame. The slowdown is about 20%.

(Background: the seek logic explicitly waits until a video frame is
displayed, because this makes it easier for the user to search for
something in the video. Without this logic, the display would freeze
until the user stops giving seek commands.)

Fix this by letting the seek logic issue another seek as soon as the
first video frame is displayed. This will prevent it from showing a
(useless, slow) second frame. Now it seems to be as fast as before the
change.

One side-effect is that the next seek happens after the first video
frame, but _before_ audio is restarted. Seeking is now silent. I guess
this is ok, so we don't do anything about it. Actually, I think whether
this happens is probably random; the seeking logic simply doesn't make
this explicit, so anything can happen.
2014-07-28 22:13:42 +02:00
wm4 261506e36e audio: change playback restart and resyncing
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.
2014-07-28 21:20:37 +02:00
wm4 6b51b73a04 player: fix idle mode event handling 2014-07-22 19:33:24 +02:00
wm4 a84517c1d8 player: don't sleep after seeks 2014-07-21 19:31:25 +02:00
wm4 0248de84ea player: simplify a condition
Move a condition somewhere else, which makes it conceptually simpler.

Also, the assignment to full_audio_buffers removed with this commit was
dead, and its value never used.
2014-07-20 20:47:30 +02:00
wm4 da1925ae2e player: simplify logic on video errors
Fatal errors in the vidoe chain (such as failing to initialize the video
chain) disable video decoding. Restart the playloop, instead of just
continuing the current iteration.

The resulting behavior should be the same, but it gets rid of possible
corner cases.
2014-07-20 20:43:06 +02:00
wm4 1313d38efb player: don't wait forever with --cache-pause-below behavior
Commit dc00b146, which disables polling by default, missed another
instance of polling: when the player pauses automatically on low cache.

This could lead to apparent freezes when playing network streams.
2014-07-20 00:16:43 +02:00