This builds but both the libmpv example and the cplayer block infinitely when
building libmpv. That's because we wait inifinitely in `dispatch_sync` as
there's no event loop in the main thread that allows for libdispatch to work..
Whiel we are at it, we should probably investigate how to use mp_dispatch
instead since it is a little lower level and could give us higher control in
building and event loop.
The subtitle timing logic always used the demuxer's start time as video
offset. This made external subtitle files "just work" with file formats
like TS, which usually have a non-0 start time. But it was wrong for
subtitles muxed with the TS, so adjust the time offset explicitly with
external files only.
Although disabling both video and audio is surely an obscure corner
case, it's allowed, and we don't want the demuxer to skip arbitrary
packets.
Basically, make the heuristic for checking interleaved files affect
external files only.
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.
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.)
Internally, there are two mechanisms which can trigger property
notification as used with "observed" properties in the client API.
The first mechanism associates events with a group of properties that
are potentially changed by a certain event. mp_event_property_change[]
declares these associations, and maps each event to a set of strings.
When an event happens, the set of strings is matched against the list of
observed properties of each client. Make this more efficient by
comparing bitsets of events instead. This way, only a bit-wise "and" is
needed for each observed property. Even better, we can completely skip
clients which have no observed properties that match.
The second mechanism just updates individual properties explicitly by
name. Optimize this by using the property index instead. It would be
nice if we could reuse the first mechanism for the second one, but
there are too many properties to fit into a 64 bit mask.
(Though the limit on 64 events might get us into trouble later...)
Almost nothing was left of it.
The only thing this commit actually removes is support for reading
input commands from stdin. But you can emulate this via:
--input-file=/dev/stdin --input-terminal=no
However, this won't work on Windows. Just use a named pipe.
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.
In encoding mode, the AO pretends to be infinitely fast (it will take
whatever we write, without ever rejecting input). Commit 261506e3 broke
this somehow. It turns out an old hack dealing with this was accidentally
dropped.
This is the hunk of code whose semantics were (partially) dropped:
if (mpctx->d_audio && (mpctx->restart_playback ? !video_left :
ao_untimed(mpctx->ao) && (mpctx->delay <= 0 ||
!video_left)))
{
int status = fill_audio_out_buffers(mpctx, endpts);
// Not at audio stream EOF yet
audio_left = status > -2;
}
This if condition is pretty wild, and it looked like it was pretty much
for audio-only mode, rather than subtle handling for encoding mode.
"Internal" events were added in the previous commits to leverage the
client API property mechanism, without making weird properties public.
But they were sent to clients too (and returned by mpv_wait_event()).
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.
This is perfectly allowed, but was ignored, because it's a corner case.
It doesn't actually wait for other clients to be destroyed, but on the
other hand I think there's no way to have other clients before
initialization.
CC: @mpv-player/stable
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"
In situations when the demuxer reports EOF, but immediately "recovers"
after that and returns new data, it could happen that audio sync was
skipped. Deal with this by actually entering the EOF state, instead of
assuming this will happen later.
Some files have the first audio much later into the video (for whatever
reasons). Instead of appending large amounts of silence to the audio
buffer (and refusing to sync if the audio to append is "too large"),
just wait until enough video has played.
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.
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.
It probably happens relatively often that the first packet (or even the
first N packets) of a stream will fail to decode, but decoding will
eventually succeed at a later point. Before commit 261506e3, this was
handled by an explicit retry loop (although this was also for other
purposes), but with then was changed to abort on the first error. This
makes it impossible to decode some audio streams.
Change this so that errors are ignored for the first 50 packets, which
should make it equivalent to the old code.
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.
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.
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.)
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.
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.
Actually free the old mmap region when readding an overlay of the same
ID without removing it before. (This is explicitly documented as
working.)
Replace the OSD atomically. Before this commit, the overlays were
removed and then readded to avoid synchronization problems.
Simplify the code: now there is no weird mapping between index and ID.
The OSD sub-bitmap list still needs to be prepared to skip unused IDs
(since each sub-bitmap list entry must be in use), but the code for this
is relatively separated now.
Fixes issue #956.
Currently entries are added after the current playlist element. This is kinda
confusing, more so given that "loadfile append" appends at the end of the
playlist.
Don't return an EOF code if there's still buffered data.
Also, don't call demux_stream_eof() in the playloop. There's probably
nothing wrong with it, but it's cleaner not to use it.
Also give AD_EOF its own value, so that a decoding error doesn't drain
audio by causing an EOF condition.
"loadfile filename append-play" will now always append the file to the
playlist, and if nothing is playing yet, start playback. I don't want to
change the semantics of "append" mode, so a new mode is needed.
Probably fixes issue #950.
This allows using external subtitle files with e.g. transport stream
files that don't start at time 0.
Note that if the .ts file has timestamp resets, everything goes south.
But I guess this was already the case before, unless there are external
subtitle files that also include timestamp resets, which is unlikely.
(On the other hand, you could for example expect that it works with
embedded DVB subtitles, that were somehow captured from the same stream
and use the same timestamps.)
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.