The status line is written from the main thread while vo_sixel, vo_kitty
and vo_tct write frames from the VO thread, so it could land inside a
frame. Add a lock that the status line holds for a write and the VOs for
a frame.
Add a new function-like macro MP_SATURATE_MUL. It multiplies a * b and
stores it in pointer "result", but sets "result" to its type's maximum
value if it overflows. Evaluates to true if it saturated, otherwise
false.
Unlike --term-playing-msg, the --term-title string is printed in an
escape sequence already. If we print other escapes during this sequence,
it will abort the sequence and dump the rest of the title string as a
visible string to the user, and possibly beep as well, since the title
string can end with a bel character.
Also updates the manpage to remove a comment about win32, since
terminal-win.c does handle OSC title sequences, calling SetConsoleTitleW.
Introduces stream_http, an internal libcurl-driven backend for http://
and https:// URLs. Runs all transfers on a dedicated curl multi thread
with a producer-side ring buffer, and exposes HTTP/2 multiplexing,
QUIC/HTTP/3 (when libcurl supports it), HSTS and TCP keep-alive.
Should generally be more stable and faster than FFmpeg HTTP/1.1 impl,
additionally connections are kept-alive between files open, so if you
open playlist of network files and navigate through them, it will re-use
the same connection.
Build is gated on the new 'libcurl' meson option (auto). When disabled
or unavailable, mpv silently falls back to FFmpeg's HTTP implementation.
Expose the terminal output sanitizer as mp_msg_sanitize() and use it in
term_osd_update_title() to sanitize the property-expanded term-title
string before it reaches mp_msg_set_term_title(). Without this, a
crafted media tag can break out of the OSC-0 sequence via embedded BEL
or ESC bytes when --term-title includes property expansions like
${media-title}.
Extend the sanitizer to cover two gaps:
- UTF-8 encoded C1 controls (U+0080-U+009F, bytes C2 80..C2 9F). xterm
in UTF-8 mode interprets these codepoints as C1 control functions
(U+009B as CSI, U+009D as OSC, U+009C as ST), allowing escape
sequence injection without any ESC or BEL bytes.
- DEL (0x7F), which was not previously filtered.
If you set file-local-options/foo at runtime and run playlist-play-index
current or playlist-play-index $current_pos, file-local-options/foo is
reset. Add a flag to make it preserve file-local-options.
The advantage of this change is that it allows binding Ctrl+r set
file-local-options/start ${=time-pos}; playlist-play-index current yes
to reload the current file while preserving all options, independently
of --no-config, --watch-later-options or --reset-on-next-file, and
without writing watch later files to disk. It also preserves
file-local-options set on the CLI unlike loadfile.
Since the previous commit normalized playlist filenames when they are
stored, the code normalizing them can be simplified back to how it was
before implementing normalization.
This normalizes the playlist/N/filename sub-property, making it
consistent with path. As a consequence playlist-path and stream-path are
also normalized.
This will allow simplifying the code by not normalizing playlist
filenames in several places, similar to 23b57e9f7f for tracks.
Currently entries in playlist files like m3u are first added to the
playlist, and then if they were relative paths the playlist file's
dirname is prepended to them.
Change it to directly add entries with the correct path. This will be
needed to normalize playlist entries as soon as they are added, else
normalization would prepend the working directory to entries with
relative paths.
demux_cue, demux_edl and demux_mkv_timeline don't need to be modified to
work with the next commit.
Sanitize the remaining control codes to mitigate malicious files or
scripts that could manipulate the terminal in unintended ways, such as
clearing the screen or changing the terminal title. While the
surface-level impact may seem minimal, control codes can be a vector for
exploiting vulnerabilities in the terminal emulator itself. This can
occur without user interaction, since file tags are displayed by default
in mpv.
Reported by: zefr0x
Since the option system now handles all the path expansion
automatically, these recent changes can be reverted for simplicity.
This reverts commit be15be3a83.
0ab3184526 introduced most of the stuff
being removed here. The idea is that when doing encoding the core should
wait until everything is initialized. This is true, but the old
implementation is overly complicated and confusing. What we need is for
both the AO to be initialized and the VO to be reconfigured for encoding
to start. Because of the way initialization works, the VO reconfig
always happens first. Changing the order in playloop would of course
break this assumption, but we can trust that nobody would arbitrarily do
that. So all that needs to be done here is that write_video should wait
until the AO is up before pushing frames. And that only applies in
encoding mode and if there is a selected audio stream in the first
place. This is a simple check.
With that in place, all of this extra junk can be dropped. We don't need
special booleans or events for the simple task of making sure the AO and
VO are both up.
Some languages actually require strings to be valid UTF-8, unlike C
which couldn't care less as long as it is NULL terminated.
Change triggered by Python support, but is also useful for Rust and Java.
removes awkward back-and-forth int -> double -> int conversion.
the last step also broke uniformity, though it likely doesn't
matter much in mpv's playlist shuffle context.
mutex itself was probably more costly than the PRNG itself. and
locking PRNGs is almost universally not recommended. simply add
a state parameter that the caller can hold to avoid locks.
This assert won't give much more information than the abort() itself. We
just want to abort on OOM there is not much to debug here. talloc macros
also doesn't add an assert.
Previously stats_time_start first sampled cpu-time and then real-time,
while stats_time_end sampled them in reverse order.
This resulted in real-time delta values being possibly a bit smaller
than the respective cpu-time deltas, which could become meaningful if
the start/end durations are consistently very short and very frequent.
In one test case (measuging the time spent at the event loop of
a script which spins on zero timeouts), this resulted in accumulated
real-time value of ~230ms per second, with a respective cpu-time
values of ~500ms. This should not be possible with single thread load.
Now start and end sample the values at the same order, so that it
balances on average. Each start/end delta now includes overhead of one
of each sample type, and excludes one of each sample type on average.
With the test case above, it's now 490 +-1 ms for both.
(the other 510ms real-time are at the excluded mpv_wait_event calls
and the unmeasured-overhead-parts of stats_time_start/end).
This fixes a bug where if stats reset happened after stats_time_start
and before stats_time_end, then the next reported cpu-time value of
that measurement was from the thread startup.
The long version:
stats resets the time-accumulated values if more than two seconds
ellapsed since last poll.
The reset keeps the elements, but makes them as if no measurement was
yet taken, so that they don't show up at new reports until a new
measurement is taken.
While the events and (untimed) cpu are reset, the timed-cpu value
was only partially reset - the values are reset but the indication
that the element is empty was not enough for stats_time_end.
So when reset happened between start/end calls, stats_time_end was
entered eventhough it shouldn't have, but with reset cpu-time value
it calculated the time since the thread's startup, hence this bug.
Further polls were ok, because they are of the delta since the
previous poll. But at the next reset it happened again.
Now the cpu-value is reset correctly, which fixes this bug.
stats_time_start and stats_time_end accumulate real-time and cpu-time
between these calls, but the total was only updated on stats_time_end.
This resulted in two issues:
- Inaccurate measured value if a report (read the perf-info property)
happened between start/end. No biggie because it's OK on average and
typically each start/end duration is quite smaller than the interval.
- If the start/end duration is bigger than the interval, then one or
more intervals had a report value (delta) of 0, and then one report
with a value bigger than the interval - which shouldn't be possible.
This commit effectively does end+start at the report time for ongoing
timed measurements, so that the report accounts for them too.
Doing end+start at the report required two more changes:
Store the element type (VAL_TIME) at stats_time_start rather than at
the end. Otherwise if the report happens after the first start but
before the first end, then the type is not yet set and the element
is skipped at the report (bypassing the end+start).
Store the thread id at the element. start/end measure the cpu-time at
the current thread so they used pthread_self(), but with the report
usually running on a different thread, it needs the thread id for the
measurement. Measuring cpu-time from a different thread is OK, and
already happens with VAL_THREAD_CPU_TIME elements during the report.
While at it, stats_time_end now uses the thread id which was stored on
start instead of using pthread_self(). This also serves as a general
protection against measuring start/end from different threads, which
would yield generally meaningless results anyway. In mpv all the
start/end calls for the same element are at the same thread.
On Windows and any other platform where cpu-time is unsuported,
previously the cpu-time was reported as 0, and now it's omitted
(at the perf-info property native value).
Code which process this report, like stats.lua, could not distinguish
between 0 which was due to unsupported platform, and "real" 0 which
indicates zero cpu activity in this poll-period.
In stats.lua this resulted in a whole lot of empty cpu graphs,
including one for every loaded script.
Now cpu-time is excluded from the report on unsupported platforms.
Real-time is obviously still being reported where requested.
Implementation wise, this is slightly hacky, by literally only
excluding the cpu-time nodes from the report itself, while keeping
all the other cpu-tinme code intact.
A more correct solution might be to identify support at compile
(configure) time, and no-op the relevant code if needed.
However, stats.c is already hacky in parts, and there's no real cost
to keeping the code active even if the result is excluded at the
report, and it's also way simpler and less bug prone. So be it.
If the cloned repo is shallow (e.g. like the default github actions
settings), the git describe command won't actually be able to fetch any
tags and will instead just get a hash. The resulting binary version
string will end up being that git hash. While it does tell you the exact
commit, it's not exactly helpful when wanting to know the general
version at a glance. For the case where we do have a git directory but
no available tags, build a version string using the mpv version + the
commit hash.
Fixes#15789.
This update introduces a demux_packet_pool, allowing for the reuse of
previously allocated packets when needed.
sizeof(AVPacket) is not a part of the lavc public ABI, which prevents us
to allocate memory in larger blocks. However, we can substantially
decrease the amount of alloc/free operations during playback by reusing
both mpv's demux_packet and AVPacket.
This adjustment addresses the root cause of issue #12076, which,
although resolved upstream, did not fully tackle the persistent problem
of allocating small blocks of aligned memory. This issue largely stems
from the FFmpeg design of the AVPacket API. After this change memory
will no longer be allocated once cache limits is reached.
The demux_packet_pool is shared as a global pool of packets for a given
MPContext.
This change significantly speeds up the demuxer deinitialization,
benefiting file switching scenarios, especially when a large demuxer
cache is used.
See: #12294
See: #12563
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
There's several path-related options that do not handle common shortcuts
(like ~/). Fix this by using mp_get_user_path where appropriate which
expands the path so users get more intuitive behavior. Fixes#15598.