0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00
Commit Graph

327 Commits

Author SHA1 Message Date
wm4
935e406d63 demux: support multiple seekable cached ranges
Until now, the demuxer cache was limited to a single range. Extend this
to multiple range. Should be useful for slow network streams.

This commit changes a lot in the internal demuxer cache logic, so
there's a lot of room for bugs and regressions. The logic without
demuxer cache is mostly untouched, but also involved with the code
changes. Or in other words, this commit probably fucks up shit.

There are two things which makes multiple cached ranges rather hard:

1. the need to resume the demuxer at the end of a cached range when
   seeking to it
2. joining two adjacent ranges when the lowe range "grows" into it (and
   resuming the demuxer at the end of the new joined range)

"Resuming" the demuxer means that we perform a low level seek to the end
of a cached range, and properly append new packets to it, without adding
packets multiple times or creating holes due to missing packets.

Since audio and video never line up exactly, there is no clean "cut"
possible, at which you could resume the demuxer cleanly (for 1.) or
which you could use to detect that two ranges are perfectly adjacent
(for 2.). The way how the demuxer interleaves multiple streams is also
unpredictable. Typically you will have to expect that it randomly allows
one of the streams to be ahead by a bit, and so on.

To deal with this, we have heuristics in place to detect when one packet
equals or is "behind" a packet that was demuxed earlier. We reuse the
refresh seek logic (used to "reread" packets into the demuxer cache when
enabling a track), which checks for certain packet invariants.
Currently, it observes whether either the raw packet position, or the
packet DTS is strictly monotonically increasing. If none of them are
true, we discard old ranges when creating a new one.

This heavily depends on the file format and the demuxer behavior. For
example, not all file formats have DTS, and the packet position can be
unset due to libavformat not always setting it (e.g. when parsers are
used).

At the same time, we must deal with all the complicated state used to
track prefetching and seek ranges. In some complicated corner cases, we
just give up and discard other seek ranges, even if the previously
mentioned packet invariants are fulfilled.

To handle joining, we're being particularly dumb, and require a small
overlap to be confident that two ranges join perfectly. (This could be
done incrementally with as little overlap as 1 packet, but corner cases
would eat us: each stream needs to be joined separately, and the cache
pruning logic could remove overlapping packets for other streams again.)

Another restriction is that switching the cached range will always
trigger an asynchronous low level seek to resume demuxing at the new
range. Some users might find this annoying.

Dealing with interleaved subtitles is not fully handled yet. It will
clamp the seekable range to where subtitle packets are.
2017-11-09 10:23:57 +01:00
wm4
4ef0887f7b demux: explicitly discard 0 sized packets
libavcodec can't deal with them, because its API doesn't distinguish
between 0 sized packets and sending EOF. As such, keeping them doesn't
do any good, ever. This actually fixes some obscure mkv sample (see
previous commit).
2017-11-06 17:13:42 +01:00
wm4
7334d93b30 demux: slightly simplify pruning
We can compute the overhead size easily now - no need for awkward
incremental updates to cached values on top of it.
2017-11-06 17:11:31 +01:00
wm4
8aa1db3b17 demux: refactoring in preparation for multiple seek range support
This adds a bunch of stuff (mostly unused or redundant) as preparation
for supporting multiple seek ranges. Actual support is probably still
far away.

One change that messes deeper with the actual code is that we account
for total buffered bytes instead of just the backwards bytes now. This
way, prune_old_packets() doesn't have to iterate over all seek ranges to
determine whether something needs pruning.
2017-11-04 23:45:21 +01:00
wm4
10d0963d85 demux: improve and optimize cache pruning and seek range determination
The main purpose of this commit is avoiding any hidden O(n^2) algorithms
in the code for pruning the demuxer cache, and for determining the
seekable boundaries of the cache. The old code could loop over the whole
packet queue on every packet pruned in certain corner cases.

There are two ways how to reach the goal:
 1) commit a cardinal sin
 2) do everything incrementally

The cardinal sin is adding an extra field to demux_packet, which caches
the determined seekable range for a keyframe range. demux_packet is a
rather general data structure and thus shouldn't have any fields that
are not inherent to its use, and are only needed as an implementation
detail of code using it. But what are you gonna do, sue me?

In the future, demux.c might have its own packet struct though. Then the
other existing cardinal sin (the "next" field, from MPlayer times) could
be removed as well.

This commit also changes slightly how the seek end is determined. There
is a note on the manpage in case anyone finds the new behavior
confusing. It's somewhat cleaner and  might be needed for supporting
multiple ranges (although that's unclear).
2017-11-04 23:18:42 +01:00
wm4
6e998be7be demux: reduce overhead when searching over keyframe ranges
The demuxer cache seeking mechanism looks at keyframe ranges to
determine the earlierst PTS of a packet. Instead of looping over all
packets twice (once to find the next keyframe, a second time to find the
seek PTS), do it in one go.

For that basically turn recompute_keyframe_target_pts() into an
iteration functionn. Functionality should be unchanged with this commit.
2017-11-04 18:18:42 +01:00
wm4
104e18214c demux: avoid excessive readahead after cache seek
The base_ts field is used to guess the decoder position, and when set to
NOPTS, it just read ahead arbitrarily. Also demux_add_packet() sets
base_ts to the new timestamp when appending a packet, which would also
make it readahead by a too large amount.

Fix this by setting base_ts after a seek. This assumes that normally, a
cached seek target will always have the timestamp set. This is actually
not quite clear (as it calls recompute_keyframe_target_pts(), which
looks at multiple packets), but maybe it works well enough.
2017-11-04 17:43:22 +01:00
wm4
c1f981f863 demux: make pruning more efficient for unseekable demuxer cache
Don't do any of the extra work related to pruning the backbuffer if
demuxer cache seeking is disabled.

As a small extra, always prune packets with no timestamps immediately,
or queue heads that are not keyframes. (Both of them would be pruned
from the backbuffer by the normal logic anyway.)
2017-11-04 17:32:34 +01:00
wm4
d46c9c2e62 demux: on queue overflow wake up reader thread on EOF only
This seems to make more sense.
2017-11-03 16:36:59 +01:00
wm4
49ae599883 demux: don't show queue overflow warning when merely prefetching
If fulfilling --demuxer-readahead-secs requires more memory than allowed
by --demuxer-max-bytes, the queue obviously overflows. But the warning
is normally only for the case when trying to find the next video or
audio packet fails, and decoding can't continue.

Use a separate variable for determining whether to prefetch, and if the
queue has overflown, skip the message. In fact, skip the EOF setting and
waking up the decoder thread as well, because the EOF flag should not be
(have been) set in this situation, and waking up the reader thread helps
only if the EOF state changed.
2017-11-03 16:36:21 +01:00
wm4
4fca1856e1 demux: don't allow subtitles to mess up buffered time display
In a shit show of subtle corner case interactions, making the demuxer
cache buffer the entire file can display a small buffered time if
subtitles are enabled. The reason is that some subtitle decoders may
read in advance infinitely, i.e. they read the entire subtitle stream.
Then, since the other streams (audio/video) have logically reached EOF,
and the subtitle stream is set to ds->active==true. This will have to be
fixed properly later to account buffering for subtitle-only files
(another corner case) correctly, but for now this is less annoying.
2017-11-03 14:58:13 +01:00
wm4
57248915fa demux: add option to create CC tracks eagerly
We don't hope to auto-detect them at load time, as that would be too
much of a pain - even FFmpeg requires fetching and parsing of video
packets, and exposes the information only via deprecated API.

But there still needs to be a way to select them by default. This is
also needed to get the first CC packet at all (without seeking back).

This commit also attempts to clean up locking a bit, which is a PITA,
but it's better be careful & clean.
2017-11-03 13:55:32 +01:00
wm4
2d958dbf2b demux: refactor to export seek ranges
Even though only 1 seek range is supported at the time.

Other than preparation for possibly future features, the main gain is
actually that we finally separate the reporting for the buffering, and
the seek ranges. These can be subtly different, so it's good to have a
clear separation.

This commit also fixes that the ts_reader wasn't rebased to the start
time, which could make the player show "???" for buffered cache amount
in some .ts files and others (especially at the end, when ts_reader
could become higher than ts_max). It also fixes writing the cache-end
field in the demuxer-cache-state property: it checked ts_start against
NOPTS, which makes no sense.

ts_start was never used (except for the bug mentioned above), so get rid
of it completely. This also makes it convenient to move the segment
check for last_ts to the demux_add_packet() function.
2017-10-30 15:28:59 +01:00
wm4
ec8cad40f2 demux: better computation of seek start target
Avoids that cache seeking is not possible with files that have audio
frames with no timestamps (such as avi, sometimes mkv sub-packets from
lacing). These would set back_pts (first seekable PTS) to NOPTS, and
thus disable cache seeking completely. Instead, prune such packets until
we find one with timestamps.

One corner case is that the new next good packet might be in the forward
cache. In this case we defer dropping until the next time this code is
run, and the reader position has possibly moved past the drop point.
2017-10-25 16:39:33 +02:00
wm4
d235380cd3 demux: reject cache seeks if parts of the range are unset
In theory, start/ts_min could be set to NOPTS, in which case
"pts < start" for a valid pts would always evaluate to false.

Also remove the redundant "in-cache seek is possible.." message, as
there's always another message when cache seeks are done.
2017-10-25 16:39:33 +02:00
wm4
03a0e8336a demux: fall back to DTS when determining seek target
Fixes AVI in particular, which abuses DTS for reordered PTS. (It's not
really DTS...)
2017-10-25 16:39:33 +02:00
wm4
e6348504b3 demux: disallow seeking if there are streams with no timestamps
The seek range computation ignored streams with no timestamps. For
things like buffer estimation this is OK and wanted, but the seek range
needs to be conservative.
2017-10-25 16:39:33 +02:00
wm4
3d71651523 demux: fix tracking of forward/backward cache size
Which parts of the queue are considered forward or backward cache
depends on ds->reader_header. The packet at ds->reader_head, as well as
all packets following it (via the ->next field) are considered forward.
The fw_packs/fw_bytes/bw_bytes must be updated accordingly.

This broke in demux_add_packet(), when ds->reader_head was _not_ set on
the first packet (or before). This could happen since commit
05ae571241, which can require skipping packets (so they immediately end
up in the backbuffer).
2017-10-25 16:39:33 +02:00
wm4
56d9dafbbb demux: respect timeline boundaries for cache seeks
With the timeline code, a packet at the start or end of a segment can
refer to an invisible frame. So it doesn't extend the seek range, and
the timestamp should be clipped to the actual segment range.

Also restructure recompute_keyframe_target_pts() to be hopefully less
confusing.
2017-10-25 16:39:33 +02:00
wm4
8bf399e02e demux: don't report unknown queue state if no packets were added
Restores some behavior from before the demuxer cache changes, though
affects mostly just OSD display. The unknown queue state is reserved for
streams with missing or messed up timestamps.
2017-10-25 16:39:33 +02:00
wm4
3d32cb1649 demux: set correct stream index for attached pictures
This fixes .cue files with audio files that contain attached pictures to
some degree. demux_timeline.c just discarded packets with unset index,
so the picture was never fed to the decoder.
2017-10-25 16:39:33 +02:00
wm4
05ae571241 demux: fix cached SEEK_FORWARD seeks into end of cached regions/EOF
Although seeking past the cached range will trigger a low level seek, a
seek into the region between cache end and last video key frame would
simply seek to the video key frame. This meant that you could get
"stuck" at the end of the file instead of terminating playback when
trying to seek past the end.

One change is that we fix this by _actually_ allowing SEEK_FORWARD to
seek past the last video keyframe in find_seek_target().

In that case, or otherwise seeking to cache buffer end, it could happen
that we set ds->reader_head=NULL if the seek target is after the current
packet. We allow this, because the end of the cached region is defined
by the existence of "any" packet, not necessarily a key frame. Seeking
there still makes sense, because we know that there is going to be more
packets (or EOF) that satisfy the seek target.

The problem is that just resuming demuxing with reader_head==NULL will
simply return any packets that come its way, even non-keyframe ones.
Some decoders will produce ugly soup in this case. (In practice, this
was not a problem, because seeking at the end of the cached region was
rare before this commit, and also some decoders like h264 will skip
broken frames by default anyway.)

So the other change of this commit is to enable key frame skipping.

As a nasty implementation detail, we use a separate flag, instead of
setting reader_head to the first key frame encounted (reader_head being
NULL can happen after a normal seek or on playback start, and then we
want to mirror the underlying demuxer behavior, for better or worse).

This change is relatively untested, so you get to keep the pieces for
yourself.
2017-10-23 20:55:11 +02:00
wm4
512509705e demux: report buffered duration of 0 during seeking instead of unknown
Looks ugly on the status line and could upset the buffering logic.
2017-10-23 19:36:20 +02:00
wm4
dbd22f43be demux: drop redundant SEEK_BACKWARD flag
Seems like most code dealing with this was for setting it in redundant
cases. Now SEEK_BACKWARD is redundant, and SEEK_FORWARD is the odd one
out.

Also fix that SEEK_FORWARD was not correctly unset in try_seek_cache().

In demux_mkv_seek(), make the arbitrary decision that a video stream is
not required for the subtitle prefetch logic to be active. We might want
subtitles with long duration even with audio only playback, or if the
file is used as external subtitle.
2017-10-23 19:05:39 +02:00
wm4
60df01512c command: read the diff if you want to know 2017-10-21 21:13:53 +02:00
wm4
633077814e *** empty log message *** 2017-10-21 20:42:40 +02:00
wm4
0004af3e71 demux: replace redundant field with a better redundant field 2017-10-21 20:36:06 +02:00
wm4
719a435d36 demux: add a back buffer and the ability to seek into it
This improves upon the previous commit, and partially rewrites it (and
other code). It does:

- disable the seeking within cache by default, and add an option to
  control it
- mess with the buffer estimation reporting code, which will most likely
  lead to funny regressions even if the new features are not enabled
- add a back buffer to the packet cache
- enhance the seek code so you can seek into the back buffer
- unnecessarily change a bunch of other stuff for no reason
- fuck up everything and vomit ponies and rainbows

This should actually be pretty usable. One thing we should add are some
properties to report the proper buffer state. Then the OSC could show a
nice buffer range. Also configuration of the buffers could be made
simpler. Once this has been tested enough, it can be enabled by default,
and might replace the stream cache's byte ringbuffer.

In addition it may or may not be possible to keep other buffer ranges
when seeking outside of the current range, but that would be much more
complex.
2017-10-21 19:26:33 +02:00
Aman Gupta
83c9f169c4 demux: optimize seeks within readahead cache
If a suitable keyframe cannot be found in each stream's
readahead cache, fallback to a regular seek.
2017-10-21 13:29:37 +02:00
wm4
044af63d98 demux: improvements to previous commits
More the ignore_eof field to the internal demux_stream struct. This is
relatively messy, because the internal struct exists only once the
stream is created, and after that setting the ignore_eof flag is a race
condition. We could bother with adding demux_add_sh_stream() parameters
for this, but let's not. So in theory a tiny race condition is
introduced, which can never be triggered since all demux API functions
are called by the playback thread only anyway.

Fix that ts_offset is accessed without log (this was introduced much
earlier by myself).

Introduce an alternative way of avoiding the annoying EOF reached
messages by not resetting the EOF flags for CC streams when a CC packet
is added. This makes the second commit in the PR which added the
original fix unnecessary.

As another cosmetic change merge the check in cached_demux_control()
into a single if().

In the future, the CC pseudo-stream should probably be replaced with an
entire pseudo-demuxer or such, which would avoid some of the messiness
(or maybe not, we don't know yet).
2017-10-20 22:30:59 +02:00
Aman Gupta
f57ff79867 demux: ignore false underrun reporting from eia_608 captions decoder 2017-10-20 22:14:54 +02:00
Raúl Peñacoba
71f97d9cf3
demux/demux: avoid redundant condition
Closes #4414
2017-07-01 15:09:12 +01:00
wm4
3fff6bc5f2 demux: change license to LGPL
As usual, the history of these files is a bit murky. It starts with the
initial commit. (At which some development had already been done,
according to the AUTHORS and ChangeLog files at the time, we should be
but covered with relicensing agreements, though.) then it goes on with
complete lack of modularization, which was cleaned up later (cd68e161).
As usual, we don't consider the copyright of the stuff that has been
moved out cleanly.

There were also contributions to generic code by people who could not be
reached or who did not agree to the relicensing, but this was all
removed.

The only patches that we could not relicense and which were still in the
current code in some form are from Dénes Balatoni: 422b0d2a, 32937181.
We could not reach him, so commits f34e1a0d and 18905298 remove his
additions. It still leaves the demux_control() declaration itself, but
we don't consider it copyrightable. It's basically an idiom that existed
in MPlayer before that change, applied to the demuxer struct. (We even
went as far as making sure to remove all DEMUXER_CTRLs the original
author added.)

Commit be54f481 might be a bit of a corner case, but this was rewritten,
and we consider the old copyright removed long ago.
2017-06-20 14:26:50 +02:00
wm4
1890529857 demux: get rid of DEMUXER_CTRL_GET_TIME_LENGTH
Similar purpose as f34e1a0dee.

Somehow this is much more natural too, and needs less code.

This breaks runtime updates to duration. This could easily be fixed, but
no important demuxer does this anyway. Only demux_raw and demux_disc
might (the latter for BD/DVD). For the latter it might actually have
some importance when changing titles at runtime (I guess?), but guess
what, I don't care.
2017-06-20 14:22:10 +02:00
wm4
f34e1a0dee demux: replace custom return codes with CONTROL_ ones
This is more uniform, and potentially gets rid of some past copyrights.

It might be that this subtly changes caching behavior (it seems before
this, it synced to the demuxer if the length was unknown, which is not
what we want.)
2017-06-19 17:56:51 +02:00
wm4
3709ce6718 demux: estimate total packet size, deprecate packet number limits
It's all explained in the DOCS changes. Although this option was always
kind of obscure and pointless. Until it is removed, the only reason for
setting it would be to raise the static default limit, so change its
default to INT_MAX so that it does nothing by default.
2017-04-14 19:19:44 +02:00
wm4
58c9f1a822 demux: try not to read packets when cancelled
Essentially, this will make it abort sooner. Especially with DASH it
might avoid confusing error messages, although exact behavior depends
on timing.
2017-02-04 22:53:04 +01:00
wm4
95d4c2d7f6 player: different way to auto-enable the demuxer cache
Instead of enabling it only when a stream-cache is enabled, also try to
enable it independently from that if the demuxer is marked as
is_network.

Also add some code to the EDL code, so EDLs containing network streams
are automatically cached this way.

Extend the OSD info line so that it shows the demuxer cache in this case
(more or less).

I didn't find where or whether options.rst describes how the demuxer
cache is enabled, so no changes there.
2017-02-02 18:38:16 +01:00
wm4
e13a62fc34 stream: better method signal caching, rename weird uncached_stream field
"uncached_stream" is a pretty bad name. It could be mistaken for a
boolean, and then its meaning would be inverted. Rename it.

Also add a "caching" field, which signals that the stream is a cache or
reads from a cache. This is easier to understand and more flexible.
2017-02-02 18:03:29 +01:00
wm4
73858bb0cc player: remove --stream-capture option/property
This was excessively useless, and I want my time back that was needed to
explain users why they don't want to use it.

It captured the byte stream only, and even for types of streams it was
designed for (like transport streams), it was rather questionable.

As part of the removal, un-inline demux_run_on_thread() (which has only
1 call-site now), and sort of reimplement --stream-dump to write the
data directly instead of using the removed capture code.

(--stream-dump is also very useless, and I struggled coming up with an
explanation for it in the manpage.)
2017-01-21 17:19:01 +01:00
wm4
880bf54d7e player: actually let cache readahead after opening demuxer for prefetch
Disabling cache readahead by default until at least 1 track is selected
is mainly for external files and such, where you don't want them to use
up resources until they're actually used.

It doesn't make sense to disable the cache for the demuxer opened for
prefetch. Also, it's fine to let it do that for the main file too (doing
or not doing it is of little consequence). That saves us from having to
distinguish them.
2017-01-19 08:00:19 +01:00
wm4
4e25feda0d player: change aspects of cover art handling
Cover art handling is a disgusting hack that causes a mess in all
components. And this will stay this way. This is the Xth time I've
changed cover art handling, and that will probably also continue.

But change the code such that cover art is injected into the demux
packet stream, instead of having an explicit special case it in the
decoder glue code. (This is somewhat more similar to the cover art hack
in libavformat.)

To avoid that the over art picture is decoded again on each seek, we
need some additional "caching" in player/video.c. Decoding it after each
seek would work as well, but since cover art pictures can be pretty
huge, it's probably ok to invest some lines of code into caching it.

One weird thing is that the cover art packet will remain queued after
seeks, but that is probably not an issue.

In exchange, we can drop the dec_video.c code, which is pretty
convenient for one of the following commits. This code duplicates a
bunch of lower-level decode calls and does icky messing with this weird
state stuff, so I'm glad it goes away.
2017-01-10 15:43:02 +01:00
wm4
334cad57c6 demux: rename a function
Also extend the comment on it.
2017-01-10 12:27:37 +01:00
wm4
0e8b9ed228 demux: uninline ds_get_packets()
It has only 1 caller, and is too far appart within the file. I think it
used to have multiple callers, but now it just doesn't make any sense to
keep it separate anymore.
2017-01-10 11:54:34 +01:00
wm4
ceb2e1026d demux, stream: add option to prevent opening referenced files
Quite irresponsibly hacked together. Sue me.
2016-12-04 23:15:31 +01:00
wm4
5838322975 demux: improve buffer estimation in a corner case
This deals with the estimation of buffered packets, which is used mostly
for display, but also things like pausing on low buffer levels.

If a stream is fully EOF (no more packets), we don't want to include it
in the total buffer amount. This also means we should make ds->eof less
flaky and more stable, so don't reset it in ds_get_packets() (this
function reset ds->eof just to retrigger a packet read attempt - we can
have this slightly simpler). This somewhat fixes buffering display when
e.g. issuing a refresh seek after re-enabling audio/video when playing
with subtitles only.
2016-11-01 16:25:40 +01:00
wm4
3a78eefc88 demux_mkv: don't recursively resolve timeline for opened reference files
Instead, resolve all references and so on in the top-level timeline.
2016-10-22 17:17:04 +02:00
wm4
61a51c57a9 demux: don't try to refresh unselected streams
This could cause nonsensical queue overflow warnings, but was otherwise
probably harmless.
2016-10-21 17:11:26 +02:00
wm4
88f10ec84f player: fix instant subtitle refresh on track switches
When switching a subtitle track, the subtitle wasn't necessarily
updated, especially when playback was paused.

Some awfully subtle and complex interactions here.

First off (and not so subtle), the subtitle decoder will read packets
only on explicit update_subtitles() calls, which, if video is active, is
called only when a new video frame is shown. (A simply video frame
redraw doesn't trigger this.) So call it explicitly. But only if
playback is "initialized", i.e. not when it does initial track selection
and decoder init, during which no packets should be read.

The second issue is that the demuxer thread simply will not read new
packets just because a track was switched, especially if playback is
paused. That's fine, but if a refresh seek is to be done, it really
should do this. So if there's either 1. a refresh seek requested, or 2.
a refresh seek ongoing, then read more packets.

Note that it's entirely possible that we overflow the packet queue with
this in unpredicated weird corner cases, but the queue limit will still
be enforced, so this shouldn't make the situation worse.
2016-09-24 19:57:19 +02:00
wm4
d4d8b3a4fc demux: do not access global options
Don't access MPOpts directly, and always use the new m_config.h
functions for accessing them in a thread-safe way.

The goal is eventually removing the mpv_global.opts field, and the
demuxer/stream-layer specific hack that copies MPOpts to deal with
thread-safety issues.

This moves around a lot of options. For one, we often change the
physical storage location of options to make them more localized,
but these changes are not user-visible (or should not be). For
shared options on the other hand it's better to do messy direct
access, which is worrying as in that somehow renaming an option
or changing its type would break code reading them manually,
without causing a compilation error.
2016-09-06 20:09:56 +02:00