2068 Commits

Author SHA1 Message Date
Kacper Michajłow 4dfee616d0 ao_wasapi: hold an MTA reference for the hotplug instance
hotplug_init runs on the thread that first reads audio-device-list and
hotplug_uninit on the core thread, so take a CoIncrementMTAUsage
reference instead of initializing an apartment on the calling thread.
2026-10-16 20:06:01 +02:00
Kacper Michajłow e470f8986e chmap_avchannel: remove mp_chmap_to_av_layout_custom()
No longer used, might be restored later.
2026-09-27 22:02:43 +02:00
Kacper Michajłow 7a40742fdc chmap_avchannel: emit native layouts for maps in native order
mp_chmap_to_av_layout_custom() emitted a custom order layout for every
known channel map, even when the map is already in libavutil's native
order and a native layout describes it exactly. libswresample treats
the two the same, but a native layout needs no allocation and describes
itself as "5.1" rather than "6 channels (FL+FR+FC+LFE+BL+BR)" in its
messages. Keep the custom order for maps that are not in native order
or contain NA channels, where it is the only exact description.
2026-09-26 17:41:34 +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
Kacper Michajłow 876ba7b283 audio: add DSD-over-PCM pass-through
Add ad_dsd, a pass-through decoder converting raw DSD audio to DoP frames, enabled with --audio-spdif=dsd. DST compressed audio is losslessly decompressed to DSD first.

DoP output requires an AO with support for the format (currently
ao_wasapi in exclusive mode) and a DoP capable DAC. Will fallback to PCM
if not supported.
2026-09-06 01:27:27 +02:00
Kacper Michajłow da166e4423 ao_wasapi: add DSD-over-PCM (DoP) output support
Map AF_FORMAT_S_DOP to 24 bits in 32-bit PCM containers, which is
how DoP is transported over WASAPI in exclusive mode. Force exclusive
mode for any non-PCM format, and don't try alternative formats for DoP.

set_ao_format() now also checks the requested format before touching
the ao configuration, because the DoP wire format reverse-maps to a
plain PCM sample format.
2026-09-06 01:27:27 +02:00
Kacper Michajłow a1b7088894 ad_lavc: request the raw bitstream from DSD decoders
FFmpeg's DSD decoders convert to PCM by default, but that conversion is
deprecated. Request AV_SAMPLE_FMT_DSD instead, will be converted by SWR,
when needed.
2026-09-06 01:27:27 +02:00
Kacper Michajłow 48fe5fca59 audio/format: add raw DSD sample format
Map FFmpeg's AV_SAMPLE_FMT_DSD to AF_FORMAT_DSD.
2026-09-06 01:27:27 +02:00
Kacper Michajłow 70fdcc9d3b audio/format: add DSD-over-PCM (DoP) sample format
AF_FORMAT_S_DOP carries pre-packed DoP frames: a marker byte and 16 DSD
bits per channel in the 24 MSBs of 32-bit samples, at 1/16th of the DSD
bit rate. Similar to IEC61937 formats, it's meant to be exclusive not
touched pass-through.
2026-09-06 01:27:27 +02:00
Dudemanguy c5d391adba ao_coreaudio: register hotplug after succesful audiounit init
No real point in registering the hotplug if we don't even know if the
actual ao is going to work or not yet. Just move it down.
2026-09-01 15:33:55 +00:00
Dudemanguy af067b5ea8 ao_coreaudio: cleanup ao on init failure
This matches what other AOs and VOs do and properly releases allocated
resources on failure.
2026-09-01 15:33:55 +00:00
Nathan Lucas 74356c0fc6 ad_spdif: only warn for required codec parameters
determine_codec_params() warns when it cannot determine a codec profile.
Some passthrough formats use fixed output parameters and do not require
the probed profile or sample rate making the warning misleading.

Warn only when a value used to configure the selected passthrough format
is missing: the profile for DTS-HD, or the sample rate for core DTS and
AC-3.

Signed-off-by: Nathan Lucas <nlucasgit@gmail.com>
2026-07-29 18:18:37 +02:00
Nathan Lucas 1388a45395 ad_spdif: recreate spdif muxer on reset
The spdif decoder uses avformat/spdifenc. Some spdifenc paths keep
muxer state across packets, such as partial TrueHD MAT frames. After a
seek, that state belongs to the old stream position and can cause the
next packet to be muxed with stale timing or buffering state.

On decoder reset, discard the current spdif muxer context. The next
usable input packet will recreate the muxer through the existing
initialization path.

Cache codec parameters from the initial probe so recreating the muxer
does not probe a partial packet after a seek or replace known values
with fallbacks.

A fresh TrueHD spdif muxer needs a TrueHD major sync before it can begin
muxing the stream. Startup or post-seek playback may begin on a TrueHD
access unit that does not have major sync, so drop TrueHD packets until
a major sync access unit is seen. This also gives the downstream decoder
a clean restart point after seeks. Warn periodically if no major sync
has been found.

Partially addresses: https://trac.ffmpeg.org/ticket/9569
Signed-off-by: Nathan Lucas <nlucasgit@gmail.com>
2026-07-29 18:18:37 +02:00
dengbo e5486b96d7 ao_pipewire: treat init timeout as failure instead of success
When wait_for_init_done times out, init_state remains INIT_STATE_NONE.
The original check only handled INIT_STATE_ERROR, allowing init() to
return 0 (success) even though the stream was never properly initialized.
This could lead to an infinite reload loop when the partially initialized
stream later enters an error state.

Fix by checking for INIT_STATE_SUCCESS instead of INIT_STATE_ERROR,
so that any state other than SUCCESS (including NONE due to timeout)
is correctly treated as a failure.
2026-07-10 00:22:51 +02:00
Mohammad AlSaleh dc8101574d audio/filter: implement lavfi-tempo leveraging lavfi's atempo/ascale
Implement `lavfi-tempo` audio filter, which uses `atempo` or `ascale`
 form libavfilter for setting the tempo.

 Users (myself included) seem to be always looking for alternative tempo
 scalers to try, and this provides a faster implementation (or two), and
 may prove useful beyond performance/speed.

 `atempo` is picked as a default, and as a fall-back if `ascale` is not
 available.

Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
2026-07-02 17:38:07 +00:00
llyyr d8c82c3b16 ao_pipewire: convert pw_time.queued from bytes to frames
pw_time.queued is reported in bytes, while the code here expects it in
nframes.

Note that this doesn't matter at all, because pw_time.queued is always 0
for us since we use it as a pull-based AO. This would be a latent bug if
we ever switched to push model.
2026-06-27 21:06:47 +02:00
llyyr 4acaa77de5 af_scaletempo: avoid memcpy with disabled overlap
Overlap can be disabled with overlap=0 or very small stride values which
cause calculated overlap size to truncate down to 0.

Fixes: https://github.com/mpv-player/mpv/issues/18107
2026-06-17 13:37:34 +00:00
nanahi 1d82932cce various: use fopen wrapper for cloexec handling 2026-06-04 04:58:16 +02:00
Kacper Michajłow f5d4d9b029 swresample: pass input layout in mpv's order via custom channel order
Drop the swr_set_channel_mapping() + transpose_order() + reorder_in[]
plumbing. Instead, build the swr input channel layout directly from the
mpv chmap as AV_CHANNEL_ORDER_CUSTOM, so the labels in the layout already
match the positions of the channels in the input data.

For all unknown map, we return all UNSPEC, so the swr expands to default
layout for this channel number.
2026-06-01 16:53:48 +02:00
llyyr 9e06c3248a ao_pipewire: avoid passing NULL to mp_msg 2026-05-22 17:51:57 +00:00
llyyr 1a78f9fa8e ao_pipewire: avoid deadlock when starting thread loop
loop_start starts a thread which immediately acquires the thread loop
lock. Locking the loop before loop_start can therefore deadlock the
newly created thread during initialization.

Locking the thread loop before loop_start was always incorrect, but
Pipewire commit fb49e0795c28* made the issue visible by switching
pw_thread_loop_lock to the underlying SPA loop lock.

To fix this, we just avoid starting the loop until after we're connected
to the server.

* https://github.com/PipeWire/pipewire/commit/fb49e0795c28c892116b03369785ba86c27c968d
2026-05-22 17:51:57 +00:00
llyyr d8be86067c ao_pulse: fix subscribe_cb using wrong bitmask for event type
PA_SUBSCRIPTION_MASK_SINK is a pa_subscription_mask constant used when
registering with pa_context_subscribe(), not a
pa_subscription_event_type mask. Masking the event type with it would
never match PA_SUBSCRIPTION_EVENT_NEW or PA_SUBSCRIPTION_EVENT_REMOVE,
causing hotplug events to be silently dropped.

Fixes: e01750020d
2026-05-03 06:44:37 +02:00
Richasy 986dd6387d ao_wasapi: fix retry budget on DEVICE_INVALIDATED
The retry path in wasapi_thread_init() used MP_TIME_US_TO_NS, giving a
total budget of ~15 us before MP_FATAL killed the audio thread. The
resulting log line "Retrying in 1000 ns" makes the unit confusion
obvious.

In practice AUDCLNT_E_DEVICE_INVALIDATED is most often hit right after
the system resumes from sleep, or when the default endpoint changes,
where the audio endpoint typically needs hundreds of milliseconds to
come back. The current budget never covers that window, so the first
playback after wake-up permanently fell back to "no audio" until the
user manually restarted playback.

Switch the retry schedule to milliseconds: start at 1 ms (~one Windows
timer tick, effectively an immediate yield), multiply by 10 each
iteration, and cap at 1 s -- i.e. 1/10/100/1000 ms, 4 retries, ~1.1 s
total. Use MP_TIME_NS_TO_MS for the warning so the unit in the log
matches reality.
2026-05-01 05:01:00 +02:00
Kacper Michajłow e757931859 af_scaletempo: limit options to resonable range
This fixes multiple overflows when passing huge values. Which causes
either invalid memory accesses when memory allocations are wrong size or
huge allocations leading to OOM.

Reported by: Trail of Bits
2026-03-23 23:34:20 +01:00
Rudi Heitbaum 8ace278cbe various: fix Wdiscarded-qualifiers warnings
Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>
2026-03-15 14:49:00 +01:00
Simonas Kazlauskas 1af136bceb ao_pipewire: remove the node.always-process attribute
With `node.always-process` mpv will force pipewire to continuously keep
driving the source node, even when paused, which causes a relatively
significant increase in power consumption due to frequent CPU wakeups.

I have tested mpv with this option disabled, both for music and video,
pausing and seeking around in various ways and could not notice any
problems with this option disabled. And with it disabled pipewire
properly becomes idle a couple seconds after video/audio is paused.

Pipewire documentation suggests that this option is largely useful for
JACK clients, which `mpv` isn't. Using GitHub-wide search it seems like
the other two notable uses of this property are really just SDL and
OpenAL. All other applications I use work well without this property
being set as well.

Note that this change does not affect the output devices differently as
far as I can tell. Both with and without `always-process` pipewire will
suspend the output device after some idle time and in case
`always-process` is enabled, it will redirect `mpv` to `Dummy-Driver`
instead.
2026-01-17 04:55:01 +00:00
llyyr f7be2ee3e9 ao_aaudio: set content type if --audio-set-media-role is enabled 2025-12-13 15:18:12 +01:00
llyyr e99daecbdb ao_audiotrack: set content type if --audio-set-media-role is enabled 2025-12-13 14:46:55 +01:00
llyyr d07e4c7935 ao_pulse: set media.role if --audio-set-media-role enabled 2025-12-13 14:46:55 +01:00
llyyr 1a802b1810 ao_pipewire: avoid setting any media.role by default
This adds option `--audio-set-media-role` to configure whether mpv
should set media roles to supported audio APIs or not. Disabled by
default.

By default, WirePlumber restores the volume of each application to
whatever the last application with the same media role used. This is
completely insane behavior, and I couldn’t find any way for a user to
opt out of it on my end. The `state-stream.lua` script responsible for
this mess only uses media.role if the property is present, so the only
reliable workaround is simply not to set one at all.

This WirePlumber behavior is inherited from PulseAudio, which also
exhibits the same behavior to this day.

This commit also mirrors the same change made to ao_pulse in 2015:
b7325b2f64

See also: https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/489
2025-12-13 14:46:55 +01:00
Jun Bo Bi 57d9d4eb42 ao/aaudio: implement aaudio backend for android 2025-11-25 20:29:42 +01:00
Jun Bo Bi 24000e3b3f meson: added option to disable audiotrack 2025-11-25 20:29:42 +01:00
llyyr b2156c7d30 ao_wasapi_utils,command,hwdec_vulkan: remove double semicolons
Cosmetic
2025-11-14 20:44:46 +00:00
Kacper Michajłow a21e47c45d ao_pipewire: fix mapping of wide channels 2025-11-14 21:41:15 +01:00
Thomas Lange 7815181b19 ao_pipewire: fix copy paste error in channel mapping 2025-11-13 18:57:22 +01:00
nanahi 8ac52fd1ab various: use mp_sleep_ns 2025-10-27 20:00:59 +01: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
Louis Pate 86e12929aa various: fix Wpedantic warnings 2025-08-01 11:56:38 +02: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
Roman Bochagov 59d5f774a4 ao_avfoundation: fix memory leak
Fix memory leak in ao_avfoundation caused by audio device switching.

Fixes #16283
2025-06-09 19:31:48 +02:00
nanahi b47c805fa2 various: remove redundant return
void return type functions don't need a final return statement.
2025-04-27 00:10:31 +02:00
Dudemanguy d9dadf07ae Revert "ao: correctly set state.playing for non-gapless audio after eof"
There's no good explanation, but I can no longer reproduce the issue
described in the commit. The code as is can cause a "File descriptor in
bad state" message when looping or advancing in a playlist because it
jumps a bit too early to the eof part. Perhaps something in alsa somehow
changed, but the non-gapless audio freezing thing doesn't happen
anymore. The audio state correctly updates on play/pause without these
lines. Since this is known to cause problems elsewhere, just revert it
for now. If the alsa problem crops up again in the future, we can
revisit it then.

This reverts commit d33e54250e.
2025-03-13 12:21:38 +01:00
Kacper Michajłow 1c49cfdb97 various: use mp_assert macro 2025-03-04 20:07:29 +01:00
llyyr c9970b5ba6 ao_pipewire: don't load client-rt.conf properties
Deprecated in https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/24bcacc6195ffbf8e40c9ea1374eb6666252eadc

Fixes: #15914
2025-02-20 15:49:01 +00:00
Dudemanguy 838df2c252 ad_lavc: flag options with UPDATE_AD 2025-01-29 15:07:42 +00: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
nanahi 0903e9fbd4 various: fix range for float options
The range of these options should be capped to FLT_MAX
instead of DBL_MAX.
2025-01-24 04:25:15 +00:00
Kacper Michajłow d66047589a ao_pulse: remove unnecessary casts and use the proper print specifier 2025-01-05 22:32:40 +01:00
Tim Lodemann 31d1defb7a ao_openal: fix null pointer dereference when creating OpenAL context
When the monitor goes to sleep, the OpenAL context was not properly
handled, resulting in a null pointer dereference and a crash. This
fix ensures that the OpenAL context is created and set correctly,
avoiding crashes under these conditions.

Fixes: #15648
2025-01-05 21:22:35 +01:00