Fixes several issues playing back mpegts with video streams marked
as having "still images". For example, see this video which has
frames only every 6s: https://s3.amazonaws.com/tmm1/music-choice.ts
Changes include:
- start playback right away, without waiting for first video frame
- do not consider the sparse video stream in demuxer underrun detection
- do not require multiple video frames for the VO
- use audio as the master stream for demuxer metadata events
- use audio stream for playback time
Signed-off-by: Aman Gupta <aman@tmm1.net>
With -v -v ("debug" level), which is the default for --log-file, this
would log every damn Matroska EBML element and some other uninteresting
things, which was very noisy.
Adjust the log levels to make them less noisy. Also, change some log
calls to MP_ERR for things which are actually errors.
Going by ISO 639.2, "und" means "Undetermined". Whatever it's supposed
to mean, in practice it's user for "unset". We prefer if the language
tag remains simply unset in this case.
This removes an ugliness with mp4 in partricular, because libavformat
will export unset languages as such, which affects most mp4 files.
This makes ICY title changes show up at approximately the correct time,
even if the demuxer buffer is huge. (It'll still be wrong if the stream
byte cache contains a meaningful amount of data.)
It should have the same effect for mid-stream metadata changes in e.g.
OGG (untested).
This is still somewhat fishy, but in parts due to ICY being fishy, and
FFmpeg's metadata change API being somewhat fishy. For example, what
happens if you seek? With FFmpeg AVFMT_EVENT_FLAG_METADATA_UPDATED and
AVSTREAM_EVENT_FLAG_METADATA_UPDATED we hope that FFmpeg will correctly
restore the correct metadata when the first packet is returned.
If you seke with ICY, we're out of luck, and some audio will be
associated with the wrong tag until we get a new title through ICY
metadata update at an essentially random point (it's mostly inherent to
ICY). Then the tags will switch back and forth, and this behavior will
stick with the data stored in the demuxer cache. Fortunately, this can
happen only if the HTTP stream is actually seekable, which it usually is
not for ICY things. Seeking doesn't even make sense with ICY, since you
can't know the exact metadata location. Basically ICY metsdata sucks.
Some complexity is due to a microoptimization: I didn't want additional
atomic accesses for each packet if no timed metadata is used. (It
probably doesn't matter at all.)
This fixes an issue where captions stop rendering after an
in-demuxer-cache seek, because the demuxer keeps waiting to find
a keyframe (ds->skip_to_keyframe set to true in execute_cache_seek).
ffmpeg marks audio tracks which are not meant to be played standalone
as DEPENDENT. these are typically used in DVB broadcasts for audio
descriptions, and are meant to be mixed into the main audio track during
playback.
I changed avio_flush() and introduced avformat_flush() exactly for this
reason.
Used with DVD/BD only (on seeks and when setting the "angle" property).
Seems to work, but wasn't tested too thoroughly (I don't care about
optical discs, I only want this ugly stuff gone that might even violate
the API/ABI).
Some shittily muxed files (by a certain HandBrake+libavformat combo)
contain a SeekHead pointing to a SeekHead at the end of the file, which
in turn points to track headers (also at the end of the file). This
failed because the demuxer didn't bother to actually read the elements
listed by the second SeekHead, so no track headers were read, and
playback broke.
Somehow commit 6fe75c38 broke this for no reason. It adds a "needed"
field, which seems completely pointless and replaced the "parsed" flag
in an incomplete way. In particular, the "needed" field was not set when
a _recursive_ SeekHead was read, so those elements were not read. Just
get rid of the field and use "parsed" instead.
Quickly tested by a person who had FFmpeg linked with libaom.
Seems as simple as the VP9 mappings, where there is no extradata/
initialization data off-band, and just stuff in the packets
themselves.
Do note that the AV1 video format itself at this point is still
not frozen, so what you might produce one day might not be
decodable the following day.
When this happens, network calls are forcibly aborted (more or less),
but demuxers might keep going, as most of them do not check for forced
exits properly. This can possibly lead to broken packets being added.
Also do not attempt to read more packets in this situation.
Also do not print a stream open failed message if opening was aborted
anyway.
Since the demuxer cache addition, ds->queue->head can actually be set to
non-NULL, but the decoder can still be at EOF (with no packets to come).
This made it report an unknown buffered size, instead of 0. Fix this by
checking the decoder part of the packet queue instead.
Probably doesn't matter much, but fixes an annoying "???" on the CLI
status line in some situations.
Naturally, there's more than one fourcc that indicates an mjpeg
stream.
I have a particular ancient webcam here (Logitech QuickCam Messanger)
that only supports the single 'JPEG' format, but there are other
devices out there which support both 'JPEG' and 'MJPG' with no visible
differences, and others where the streams are slightly different.
Regardless of those details, it remains correct to treat 'JPEG'
the same as 'MJPG' from a stream consumption perspective.
It's a mess: mp3 files have user tags as global metadata (because the
id3v2 tag is global and there is only 1 stream), while OGG files have it
per-track (because it's per-stream on the lowest level). mpv needs to
try to make something nice out of the mess.
It did so by trying to detect audio-only OGG files, and then copying the
per-stream metadata to the global metadata. Make the heuristic for
detecting this slightly more clever, so it works for files with extra,
unrelated streams, like the awful libavformat cover art hack.
Fixes#5577.
It appears some (or all) mkv files with EAC3 are muxed in a way that
breaks FFmpeg's spdifenc. I suspect it's because either dependent
substream packets are localted in their own packets, or the reverse. Or
possibly this is case where the muxer did not respect packet boundaries
at all. Enabling the EAC3 parser seems to fix this anyway, because why
waste your precious time on retarded Dolby bullshit technology? (Which
idiot came up with this shitty substream garbage?)
Observed with dolby_digital_plus_channel_check_lossless-DWEU.mkv.
Fixes#5578.
This includes codec/muxer/demuxer iteration (different iteration
function, registration functions deprecated), and the renaming of
AVFormatContext.filename to url (plus making it a malloced string).
Libav doesn't have the new API yet, so it will break. I hope they will
add the new APIs too.
Reduce backward/forward from 400MB/400MB to 50MB/150MB. Too many
complaints about high memory usage.
Note that external tracks (like ytdl DASH with external audio tracks)
will double the amounts, because an external track uses its own demuxer
and cache.
This reverts commit b7f90be567.
The author agreed to the relicensing now (if that code is affected by
the original copyright at all - that was the only line possibly left of
it).
If tags like TITLE have the whole parameter in " quotes, strip them.
Also remove the leading whitespace, since even with a single space it
was always included.
Fixes#5462.
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
This is supposed to help making data flow easier and wakeup handling
more efficient. Once that change is done, reading a packet on any
stream won't have to wakeup and poll all decoders (which helps reducing
the mess even if all decoders are on the same thread).
This also improves the accuracy of wakeups by tracking better whether
a wakeup is needed.
AV_DISPOSITION_ATTACHED_PIC usually means the video track isn't real,
and merely reflects the presence of an embedded image in tag data (such
as ID3v2 tags), with some inconsistent hack to make libavformat return
it as video packet once.
Except it doesn't mean that. It can be randomly set on other streams
that do sort of behave like video streams, such as chapter thumbnail
tracks in mp4 files. AV_DISPOSITION_TIMED_THUMBNAILS is set in these
cases. In theory, there can supposedly be more such cases, but only the
chapter thumbnail one currently exists. So add it as exception.
This restores displaying these thumbnails as video frames, for better or
worse. (Before, only the first thumbnail was displayed.)
Requires newest FFmpeg git, which has a change that makes the HLS
demuxer set an AVFMTCTX_UNSEEKABLE flag if seeking is not available,
which is the case for HLS live streams. This should make the player
frontend behave pretty well, instead of crapping up irrecoverably.
And use it for 2 demuxer options. It could be used for more options
later. (Though the --cache options can not use this, because they use KB
as base unit.)
I found that at least for mjpeg streams, FFmpeg will set packet pts/dts
anyway. The mjpeg raw video demuxer (along with some other raw formats)
has a "framerate" demuxer option which defaults to 25, so all mjpeg
streams will be played at 25 FPS by default.
mpv doesn't like this much. If AVFMT_NOTIMESTAMPS is set, it prints a
warning, that might print a bogus FPS value for the assumed framerate.
The code was originally written with the assumption that FFmpeg would
not set pts/dts for such formats, but since it does, the printed
estimated framerate will never be used. --fps will also not be used by
default in this situation.
To make this hopefully less confusing, explicitly state the situation
when the AVFMT_NOTIMESTAMPS flag is set, and give instructions how to
work it around.
Also, remove the warning in dec_video.c. We don't know what FPS it's
going to assume anyway. If there are really no timestamps in the stream,
it will trigger our normal missing pts workaround. Add the assumed FPS
there.
In theory, we could just clear packet timestamps if AVFMT_NOTIMESTAMPS
is set, and make up our own timestamps. That is non-trivial for advanced
video codecs like h264, so I'm not going there. For seeking and
buffering estimation the situation thus remains half-broken.
This is a mitigation for #5419.
It was actually already implemented as ta_dup_ptrtype(), but that seems
like a clunky name. Also we still use the talloc_ names throughout the
source, and I'd rather use an old name instead of a mixing inconsistent
naming conventions.
If you play a video with an external audio track, and do backwards
keyframe seeks, then audio can be missing. This is because a backwards
seek can end up way before the seek target (this is just how this seek
mode works). The audio file will be seeked at the correct seek target
(since audio usually has a much higher seek granularity), which results
in silence being played until the video reaches the originally intended
seek target.
There was a hack in audio.c to deal with this. Replace it with a
different hack. The new hack probably works about as well as the old
hack, except it doesn't add weird crap to the audio resync path (which
is some of the worst code here, so this is some nice preparation for
rewriting it). As a more practical advantage, it doesn't discard the
audio demuxer packet cache. The old code did, which probably ruined
seeking in youtube DASH streams.
A non-hacky solution would be handling external files in the demuxer
layer. Then chaining the seeks would be pretty easy. But we're pretty
far from that, because it would either require intrusive changes to the
demuxer layer, or wouldn't be flexible enough to load/unload external
files at runtime. Maybe later.
Similar to 1eec7d2315, but for the beginning of the stream (named BOF in
this commit).
We can know this only if demuxing actually started from the beginning.
If there is a seek to the beginning (even if you use --start=-1000), we
don't know in general whether the demuxer truly returns the start of the
file. We could probably make a heuristic with assuming that this is what
happens if the seek target is before the start time or so, but this is
not included in this commit.
libavformat's cover art hack (aka attached pictures) breaks the ability
of the demuxer cache to keep multiple seek ranges. This happens because
the cover art packet has neither position nor timestamp, and libavformat
gives us the packet even though we intended to drop it.
The cover art hack works by adding the cover art packet to the read
packet stream once when demuxing starts (or after seeks). mpv treats
cover art in a similar way internally, but we have to compensate for
libavformat's shortcomings, and add the cover art packet ourselves when
we need it. So we don't want libavformat to return the packet.
We normally prevent this in demux_lavc.c/select_tracks() and explicitly
disable cover art streams. (We add it in dequeue_packet() instead.) But
libavformat will actually add the cover art packet even if we disable
the cover art stream, because it adds it at initialization time, and
does not bother to check again in av_read_frame() (apparently). The
packet is actually read, and upsets the demuxer cache logic. In
addition, this also means we probably decoded the cover art picture
twice in some situations.
Fix this by explicitly checking/discarding this in yet another place.
(Screw this hack...)
The impact was that you couldn't exactly seek to the join point with a
keyframe seek, even though there was a keyframe. This commit fixes it by
preserving the necessary metadata that got lost on cached range joining.
This is so absurdly obscure that it gets a longer code comment.
This warning was printed when the demuxer cache tried to join two
adjacent seek ranges, but failed if the last keyframe in the second
range was within the (overlapping) first range. This is a weird corner
case which to support probably would not be worth it.
So this code just printed a warning and discarded the second range. As
it turns out, this can happen relatively often if you seek a lot, and
the seek ranges are very tiny (such as consisting of only 1 keyframe).
Dropping the second range in these cases is OK and probably cheaper than
trying to actually join them. Change the warning to verbose level.
(It seems this could actually be "supported", because if keyframe_latest
is not set, there will be no other keyframes, so it could just be unset,
with the exception that q1->keyframe_latest in the code below must not
be overwritten. But still, too much trouble for a special case that
likely does not matter, and it would have to be tested too.)
This means if the user tries to seek past EOF, and we know EOF was seen
already, then use a cached seek, instead of triggering a low level seek.
This requires some annoying tracking, but seems pretty simple otherwise.
One advantage of doing this is that if the user tries to do this kind of
seek, there's no unnecessary waiting for a reaction by network (and in
most cases, redundant downloading of data just to discard it again).
Another is that this avoids creating overlapping seek ranges: previously, the
low level seek would naturally create a new range. Then it would read and add
data from the end of the stream due to the low level demuxer not being able to
seek to the target and selecting the last seek point before the end of the
stream. Consequently, this new range would overlap with the previous cached
range. But since the cache joining code is written such that you join the
current range with the _next_ range (instead of the previous as it would be
needed in this case), the overlapping ranges were left alone, until seeking back
to the previous range. That was ugly, sort of harmless, and could happen in
other cases, but this avoidable case was pretty easy to trigger.
Export them as explicitly undocumented debugging fields for the
"demuxer-cache-state" property.
Should be somewhat helpful to debug "wtf is the demuxer" doing
situations better, especially when seeking. It also becomes visible how
long the demuxer is blocked on an "old" seek when you keep seeking while
the first seek hasn't finished.
update_seek_ranges() has some special code that attempts to correctly
adjust seek ranges for subtitle tracks. (Subtitle are a nightmare for
seek ranges, because they are sparse, so using the packet list is not
enough to reliably determine the valid cached range.)
This had code like this inside the modified if statement:
range->seek_start = MP_PTS_MAX(range->seek_start, <something>);
If seek_start is NOPTS, then seek_start will be set to <something>,
breaking some other code that checks seek_start for NOPTS to see if it's
empty. Fix this by explicitly checking whether seek_start is NOPTS
before adjusting it.
The crash happened in prune_old_packets() because the range was marked
as non-empty, yet there was no packet in it to prune. This was with
files with muxed subtitles, when seeking back to the start. This should
not happen anymore with the change. Also add an assert() to
check_queue_consistency() that checks for this specific case.
There's still some mess. In theory, subtitle tracks could be completely
empty, yet their seek range would span the entire file. Seek range
tracking of subtitle files is slightly broken (even before this change).
Some of this should probably be revisited later, including not just
using seek_start to determine whether a seek range should be pruned due
to being empty.
The x264 hack requires reading the first video packet, which in turn we
handle with a hack in demux_mkv.c to get the packet without having to
add special crap to demux.c. Another useless MKV feature (which they
enabled by default at one point and which caused many demuxers to break
completely, only to disable it again when it was too late) conflicts
with this, because we actually pass a block as packet contents, instead
of after "decompression".
Fix this by calling demux_mkv_decode().
This fixes when resuming certain broken h264 files encoded by x264. See
FFmpeg commit 840b41b2a643fc8f0617c0370125a19c02c6b586 about the x264
bug itself.
Normally, the unregistered user data SEI (that contains the x264 version
string) is informational only. But libavcodec uses it to workaround a
x264 bug, which was recently fixed in both libavcodec and x264. The fact
that both encoder and decoder were buggy is the reason that it was not
found earlier, and there are apparently a lot of files around created by
the broken decoder. If libavcodec sees the SEI, this bug can be worked
around by using the old behavior.
If you resume a file with mpv (i.e. seeking when the file loads),
libavcodec never sees the first video packet. Consequently it has to
assume the file is not broken, and never applies the workaround,
resulting in garbage being played.
Fix this by always feeding the first video packet to the decoder on
init, and then flushing the codec (to avoid that an unwanted image is
output). Flushing the codec does not remove info such as the x264
version. We also abuse the fact that the first avcodec_send_packet()
always pushes the frame into the decoder (so we don't have to trigger
the decoder by requsting an output frame).
This will help with things like livestreams.
As a minor detail, subtitles are excluded, because they sometimes have
"unused" events after video and audio ends. To avoid this annoying
corner case, just ignore them.
Before this change and before the seekable stream cache became a thing,
we could possibly seek using the stream cache. But we couldn't know
whether the seek would succeed. We knew the available byte range, but
could in general not tell whether a demuxer would stay within the range
when trying to seek to a specific time position. We preferred to have
safe defaults, so seeking in streams that were detected as unseekable
were not honored. We allowed overriding this via --force-seekable=yes,
in which case it depended on your luck whether the seek would work, or
the player crapped its pants.
With the demuxer packet cache, we can tell exactly whether a seek will
work (at least if there's only 1 seek range). We can just let seeks go
through. Everything to allow this is already in place, and this commit
just moves around some minor things.
Note that the demux_seek() return value was not used before, because low
level (i.e. network level) seeks are usually asynchronous, and if they
fail, the state is pretty much undefined. We simply repurpose the return
value to signal whether cache seeking worked. If it didn't, we can just
resume playback normally, because demuxing continues unaffected, and no
decoder are reset.
This should be particularly helpful to people who for some reason stream
data into stdin via streamlink and such.