484 Commits

Author SHA1 Message Date
Kacper Michajłow 12d630d819 terminal: serialize terminal output between the status line and the VOs
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.
2026-10-11 16:45:32 +02:00
Kacper Michajłow 38aed4d1f2 common/encode_lavc: prefix global functions with mp_
To avoid conflicts with xavs2.
2026-09-26 00:49:37 +02:00
nanahi 97db44f89f common/playlist: add playlist_set_params function
Helper function to set file local options for all entries. Will be used
in the next commit.
2026-07-26 11:49:16 +02:00
Kacper Michajłow fc26cd23c0 msg: strip raw C1 controls and skip valid UTF-8 in sanitize
Fixes: #17957
2026-06-27 18:55:17 +02:00
Nicolas F f5a894de87 common/common: add saturating multiply macro
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.
2026-06-27 18:10:47 +02:00
Kacper Michajłow f88f423829 meson: consider only 'v0.*' tags when computing the version
This allow creating other tags on the repository and don't interfere
with version string generated.
2026-06-05 07:21:58 +02:00
Mikael Magnusson 7d603534de msg: don't allow any escapes in --term-title
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.
2026-05-20 10:56:08 +02:00
Kacper Michajłow c6833a9307 stream_curl: add libcurl-based stream backend
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.
2026-05-16 18:20:42 +02:00
Kacper Michajłow 9b3565c980 msg: don't filter PU{1,2} we use them internally
Fixes: #17801
Fixes: d4ae20b7a3
2026-04-23 17:13:42 +02:00
rabbit d4ae20b7a3 msg: sanitize term title and block C1 controls and DEL
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.
2026-04-20 21:53:33 +02:00
llyyr 8665237a07 wayland: use av_gcd instead of implementing our own gcd function
Adds mp_gcd wrapper for av_gcd and uses it instead.
2026-04-18 17:55:26 +02:00
nanahi da2739f44f various: don't check if endptr is null for strto[udll]
These functions always set endptr to non-null so there is no need to
check.
2026-04-17 04:09:23 +02:00
Guido Cella 3b555c349c command: let playlist-play-index current preserve file-local-options
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.
2026-02-27 09:21:14 +01:00
nanahi 3eb8f9a1de demux_lavf: get codec info from AVCodecParameters
This allows displaying codec info for all tracks without selecting the
track.
2026-02-24 19:36:33 +01:00
Guido Cella fc86b96a8a various: don't normalize playlist filenames again
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.
2026-01-12 15:10:37 +00:00
Guido Cella dfb4164097 common/playlist: store normalized playlist filenames
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.
2026-01-12 15:10:37 +00:00
Guido Cella 2871471f31 demux_playlist: add base paths when adding playlist entries
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.
2026-01-12 15:10:37 +00:00
Kacper Michajłow 6c160f1aa8 common/msg: allow only SGR sequence in terminal output
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
2026-01-06 13:57:21 +01:00
Kacper Michajłow 72efbfd009 version.h.in: bump copyright year 2026-01-01 13:26:59 +01:00
Kacper Michajłow 3d39d992d0 av_common: check if position is not negative 2025-10-07 07:55:26 +02:00
Kacper Michajłow 4338880560 various: add MP prefix for {PRINTF,SCANF}_ATTRIBUTE 2025-10-05 21:34:29 +02:00
Dudemanguy 29307c26ba Reapply "various: expand paths for all file/directory related options"
This reverts commit 43fda5442f.
2025-08-08 01:07:00 +00:00
Dudemanguy 43fda5442f Revert "various: expand paths for all file/directory related options"
Since the option system now handles all the path expansion
automatically, these recent changes can be reverted for simplicity.

This reverts commit be15be3a83.
2025-07-22 17:52:41 +00:00
Dudemanguy 1fbf1e1d91 encode: simplify all initial blocking logic for encoding
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.
2025-07-14 22:09:49 +00:00
dyphire 2d149e007f misc/language: parse default tag from external subtitle tracks 2025-07-06 12:52:22 +02:00
Kacper Michajłow 3d5949366c {osd,msg}: use PU{1,2} for escape codes instead of invalid Unicode
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.
2025-04-09 18:09:03 +02:00
NRK 22f4ff44c5 misc/random: add mp_rand_in_range32()
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.
2025-04-02 17:28:49 +02:00
NRK dd29542f6f misc/random: eliminate mutex
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.
2025-04-02 17:28:49 +02:00
Tom Grimwood-Taylor f608780032 misc/language: parse forced tag from external subtitle tracks
Fixes: mpv-player#16060
2025-03-31 11:47:52 +02:00
Kacper Michajłow 1c49cfdb97 various: use mp_assert macro 2025-03-04 20:07:29 +01:00
Kacper Michajłow 6ad1575cf6 common/common: remove assert from MP_HANDLE_OOM
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.
2025-03-04 20:07:29 +01:00
Kacper Michajłow d37405c8f3 common/av_log: make FFmpeg libs ABI mismatch log clearer
And exit, instead of aborting.
2025-03-03 10:44:44 -05:00
Kacper Michajłow 962fb5fde8 common/av_log: show also build version for FFmpeg 2025-03-03 10:44:44 -05:00
Kacper Michajłow 275b93b256 common/stats: print percentage of elapsed time during sampling time 2025-02-25 05:40:14 +01:00
Kacper Michajłow 6c075b0791 common/stats: add one more digit to stats timing 2025-02-25 05:40:14 +01:00
Kacper Michajłow b313a6ea34 common/stats: move formatting code to one place 2025-02-25 05:40:14 +01:00
Kacper Michajłow d759e26fd0 libmpv: use correct header directory name
libmpv headers are installed to `mpv/`, so why are we pretending it is
`libmpv`?

Fixes documentation, libmpv meson dependency, tests.
2025-02-23 01:40:12 +01:00
Kacper Michajłow 77313f73a2 various: reduce the include scope of some public headers 2025-02-23 01:40:12 +01:00
Avi Halachmi (:avih) 1c3eecd821 common/stats: improve accuracy of quick timed measurements
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).
2025-02-17 22:50:03 +01:00
Avi Halachmi (:avih) be68ca94ad common/stats: fix incorrect cpu-time value reset
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.
2025-02-17 22:50:03 +01:00
Avi Halachmi (:avih) 7162c960e7 common/stats: report: account for ongoing timed-measuremets
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.
2025-02-17 22:50:03 +01:00
Avi Halachmi (:avih) 40fb226cc2 common/stats: don't report cpu-time on unsupported platforms
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.
2025-02-17 22:50:03 +01:00
Kacper Michajłow 17db9bdc50 build: add early exit if git is not found
Also fallback to `--always` only if first `git describe` returned
errors, but were called successfully.
2025-02-06 02:16:51 +01:00
Kacper Michajłow 05ff82e153 build: use a more user-friendly version string for shallow clones
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.
2025-02-05 23:17:06 +00:00
Dudemanguy 8e97f41849 build: prepend version strings with 'v' for release tarball builds
This was an inconsistency with the git tagging since the meson project
version is just a number.
2025-02-05 23:17:06 +00:00
Kacper Michajłow 038d66549d demux: reclaim demux_packets to reduce memory allocator pressure
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>
2025-02-05 05:09:33 +01:00
Dudemanguy be15be3a83 various: expand paths for all file/directory related options
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.
2025-01-29 14:49:06 +00:00
Kacper Michajłow 59d1dc43b9 various: fix typos 2025-01-04 15:59:49 +02:00
Kacper Michajłow e01f75e636 version.h.in: bump copyright year 2025-01-03 01:21:15 +01:00
Kacper Michajłow 04eb51246f options: remove old compatibility definitions
This makes things more readable.
2024-12-09 19:19:50 +01:00