Commit Graph

1608 Commits

Author SHA1 Message Date
wm4 32e3033666 ad_lavc: skip fully skipped frames
Fixes stupid messages with a opus/mkv test file that had an absurdly
huge codec delay.

This file fully skips several frames at the start. ad_lavc.c trimmed
these frames to 0 samples and returned them. The next layer
(f_decoder_wrapper.c) saw discontinuous PTS values, because the PTS
values increased by a frame, but amounted to 0 audio samples. This was
harmless, but logged PTS discontinuity errors.
2019-09-19 20:37:04 +02:00
wm4 b9d351f02a Implement backwards playback
See manpage additions. This is a huge hack. You can bet there are shit
tons of bugs. It's literally forcing square pegs into round holes.
Hopefully, the manpage wall of text makes it clear enough that the whole
shit can easily crash and burn. (Although it shouldn't literally crash.
That would be a bug. It possibly _could_ start a fire by entering some
sort of endless loop, not a literal one, just something where it tries
to do work without making progress.)

(Some obvious bugs I simply ignored for this initial version, but
there's a number of potential bugs I can't even imagine. Normal playback
should remain completely unaffected, though.)

How this works is also described in the manpage. Basically, we demux in
reverse, then we decode in reverse, then we render in reverse.

The decoding part is the simplest: just reorder the decoder output. This
weirdly integrates with the timeline/ordered chapter code, which also
has special requirements on feeding the packets to the decoder in a
non-straightforward way (it doesn't conflict, although a bugmessmass
breaks correct slicing of segments, so EDL/ordered chapter playback is
broken in backward direction).

Backward demuxing is pretty involved. In theory, it could be much
easier: simply iterating the usual demuxer output backward. But this
just doesn't fit into our code, so there's a cthulhu nightmare of shit.
To be specific, each stream (audio, video) is reversed separately. At
least this means we can do backward playback within cached content (for
example, you could play backwards in a live stream; on that note, it
disables prefetching, which would lead to losing new live video, but
this could be avoided).

The fuckmess also meant that I didn't bother trying to support
subtitles. Subtitles are a problem because they're "sparse" streams.
They need to be "passively" demuxed: you don't try to read a subtitle
packet, you demux audio and video, and then look whether there was a
subtitle packet. This means to get subtitles for a time range, you need
to know that you demuxed video and audio over this range, which becomes
pretty messy when you demux audio and video backwards separately.

Backward display is the most weird (and potentially buggy) part. To
avoid that we need to touch a LOT of timing code, we negate all
timestamps. The basic idea is that due to the navigation, all
comparisons and subtractions of timestamps keep working, and you don't
need to touch every single of them to "reverse" them.

E.g.:

    bool before = pts_a < pts_b;

would need to be:

    bool before = forward
        ? pts_a < pts_b
        : pts_a > pts_b;

or:

    bool before = pts_a * dir < pts_b * dir;

or if you, as it's implemented now, just do this after decoding:

    pts_a *= dir;
    pts_b *= dir;

and then in the normal timing/renderer code:

    bool before = pts_a < pts_b;

Consequently, we don't need many changes in the latter code. But some
assumptions inhererently true for forward playback may have been broken
anyway. What is mainly needed is fixing places where values are passed
between positive and negative "domains". For example, seeking and
timestamp user display always uses positive timestamps. The main mess is
that it's not obvious which domain a given variable should or does use.

Well, in my tests with a single file, it suddenly started to work when I
did this. I'm honestly surprised that it did, and that I didn't have to
change a single line in the timing code past decoder (just something
minor to make external/cached text subtitles display). I committed it
immediately while avoiding thinking about it. But there really likely
are subtle problems of all sorts.

As far as I'm aware, gstreamer also supports backward playback. When I
looked at this years ago, I couldn't find a way to actually try this,
and I didn't revisit it now. Back then I also read talk slides from the
person who implemented it, and I'm not sure if and which ideas I might
have taken from it. It's possible that the timestamp reversal is
inspired by it, but I didn't check. (I think it claimed that it could
avoid large changes by changing a sign?)

VapourSynth has some sort of reverse function, which provides a backward
view on a video. The function itself is trivial to implement, as
VapourSynth aims to provide random access to video by frame numbers (so
you just request decreasing frame numbers). From what I remember, it
wasn't exactly fluid, but it worked. It's implemented by creating an
index, and seeking to the target on demand, and a bunch of caching. mpv
could use it, but it would either require using VapourSynth as demuxer
and decoder for everything, or replacing the current file every time
something is supposed to be played backwards.

FFmpeg's libavfilter has reversal filters for audio and video. These
require buffering the entire media data of the file, and don't really
fit into mpv's architecture. It could be used by playing a libavfilter
graph that also demuxes, but that's like VapourSynth but worse.
2019-09-19 20:37:04 +02:00
sfan5 8f96169117 ao_opensles: fix delayed audio
This was forgotten in commit 5a8c48fde2
when the number of buffers was reduced to 1.
2019-09-02 00:38:05 +03:00
Aman Gupta 8b114e574a ao/audiounit: include AVAudioSession buffer in latency calc
Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-04-05 10:29:44 +07:00
Aman Gupta e35aca3cb4 ao/audiounit: improve a/v sync
This more closely mimics ao_coreaudio, on which this driver was
originally based.

Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-04-05 10:29:44 +07:00
Anton Kindestam 8b83c89966 Merge commit '559a400ac36e75a8d73ba263fd7fa6736df1c2da' into wm4-commits--merge-edition
This bumps libmpv version to 1.103
2018-12-05 19:19:24 +01:00
Jan Ekström 4056a9a420 ad_spdif: cosmetic alignment 2018-10-30 02:13:04 +02:00
Jan Ekström 25ee18d6e5 ad_spdif: fix DTS-HD HRA handling
Apparently, for bit streaming DTS-HD MA is specified to be handled as an
eight channel (7.1) bit stream, while DTS-HD HRA is specified to be
handled as a stereo bit stream.

Define a variable for this, and utilize it to set the correct values
for both the DTS-HD bit streaming rate, as well as the channel count
for the SPDIF encoder.

Fixes #6148
2018-10-30 02:13:04 +02:00
Josh Lehman 515c4163ea ao_audiounit: rename pause function to reset
AudioUnit output driver uses the pull based api so it should have
a reset function instead of a pause function.
2018-09-30 16:01:21 -07:00
Jan Ekström cea4ff3e5f ao_alsa: log the ALSA state if we get a non-XRUN error
The ALSA state generally can tell us more information in case we
get an unexpected error.
2018-09-29 20:02:46 +02:00
Jan Ekström fdc952486a ao_alsa: handle XRUNs separately from other errors
According to ALSA doxy, EPIPE is a synonym to SND_PCM_STATE_XRUN,
and that is a state that we should attempt to automatically recover
from. In case recovery fails, log an error and return zero.

A warning message will still be output for each XRUN since those
are not something we should generally be receiving.
2018-09-29 20:02:46 +02:00
Jan Ekström 3218a58082 ao_alsa: early exit get_space if paused or ALSA is not ready
This has been way too long coming, and for me to notice that a
whole lot of ao_alsa functions do an early return if the AO is
paused.

For the STATE_SETUP case, I had this reproduced once, and never
since. Still, seems like we can start calling this function before
the ALSA device has been fully initialized so we might as well
early exit in that case.
2018-09-29 20:02:46 +02:00
Niklas Haas fed0ea111b ao_jack: only auto-connect to audio ports
This prevents ao_jack from auto-connecting to MIDI ports (or other,
hypothetical future port types).
2018-09-26 22:44:48 +03:00
Tom Yan 9d6b15ab32 ao_pulse: fix tlength calculation
also remove the now unused non-sensical af_fmt_seconds_to_bytes.
2018-09-01 16:14:11 +02:00
Michael Hoang 91786fa99c Revert "ao_openal: enable building on OSX"
This reverts commit af6126adbe. Apple's
OpenAL support is ridiculously out of date, revert back to just using
OpenAL Soft on macOS (fixes #4645).
2018-08-26 15:49:22 +03:00
Hector Martin a10754f038 af_rubberband: reset delay to 0 on reset
This fixes A-V drift on seeking
2018-08-25 19:20:42 +03:00
Tom Yan 6c2d6a3046 ao_opensles: set numBuffers to 8
Apparently some Android builds/forks require this for Bluetooth
audio to work as they unexpectedly accept fast flag for it.

Shouldn't cause any side-effect (e.g. buffer requirement increased
when on wired audio). It's a hardcoded default in the upstream
AAudio implementation anyway.

Ref.:
https://android.googlesource.com/platform/frameworks/av/+/android-8.0.0_r1/media/libaaudio/src/legacy/AudioStreamTrack.cpp#109
https://android.googlesource.com/platform/frameworks/wilhelm/+/android-8.0.0_r1/src/android/AudioPlayer_to_android.cpp#1680
https://android.googlesource.com/platform/frameworks/av/+/android-8.0.0_r1/media/libaudioclient/AudioTrack.cpp#488
2018-08-13 19:10:10 +02:00
Tom Yan f2311ff514 audio/format: decouple af_fmt_is_planar from af_fmt_to_planar
so that af_fmt_to_planar (and hence af_fmt_from_planar) can just
return the input when it is not an interleaved (planar) format.
2018-08-11 11:56:27 +02:00
Tom Yan e1bd5288b7 ao_opensles: rework the heuristic of buffer/enqueue size setting
ao->device_buffer will only affect the enqueue size if the latter
is not specified. In other word, its intended purpose will solely
be setting/guarding the soft buffer size.

This guarantees that the soft buffer size will be consistent no
matter a specific enqueue size is set or not. (In the past it
would drop to the default of the generic audio-buffer option.)

opensles-frames-per-buffer has been renamed to opensles-frames-per
-enqueue, as it was never purposed to set the soft buffer size. It
will only make sure the size is never smaller than itself, just as
before.

opensles-buffer-size-in-ms is introduced to allow easy tuning of
the relative (i.e. in time) soft buffer size (and enqueue size,
unless the aforementioned option is set). As "device buffer" never
really made sense in this AO, this option OVERRIDES audio-buffer
whenever its value (including the default) is larger than 0.

Setting opensl-buffer-size-in-ms to 1 allows you to equate the soft
buffer size to the absolute enqueue size set with opensl-frames-per
-enqueue conveniently (unless it is less than 1ms).

When both are set to 0, audio-buffer will be the ultimate fallback.
If audio-buffer is also 0, the AO errors out.
2018-08-05 17:52:01 +02:00
Tom Yan 8baad91e7b ao_opensles: allow s32 and float output
OpenSLES (and its AudioTrack backend) in Android can take 32-bit
fixed and floating point input since Android L (API 21).
2018-08-05 17:51:45 +02:00
Tom Yan 4e91cb72ef audio/format: minor fix for af_fmt_from_planar
See af_fmt_to_planar.
2018-08-05 17:51:45 +02:00
Jan Ekström 36cc33ff5a ao_alsa: simplify get_space() 2018-06-04 00:03:11 +03:00
Muhammad Faiz 945303a92e ao_alsa: replace snd_pcm_status() with snd_pcm_avail() in get_space()
Fixes a bug with alsa dmix on Fedora 29. After several minutes,
audio suddenly becomes bad and muted.

Actually, I don't know what causes this. Probably this is a bug in alsa.
In any case, as snd_pcm_status() returns not only 'avail', but also other
fields such as tstamp, htstamp, etc, this could be considered a good
simplification, as only avail is required for this function.
2018-06-04 00:00:57 +03:00
wm4 f8ab59eacd player: get rid of mpv_global.opts
This was always a legacy thing. Remove it by applying an orgy of
mp_get_config_group() calls, and sometimes m_config_cache_alloc() or
mp_read_option_raw().

win32 changes untested.
2018-05-24 19:56:35 +02:00
wm4 fb22bf2317 ao: use a local option struct
Instead of accessing MPOpts.
2018-05-24 19:56:35 +02:00
wm4 e02c9b9902 build: make encoding mode non-optional
Makes it easier to not break the build by confusing the ifdeffery.
2018-05-03 01:08:44 +03:00
wm4 0ab3184526 encode: get rid of the output packet queue
Until recently, ao_lavc and vo_lavc started encoding whenever the core
happened to send them data. Since audio and video are not initialized at
the same time, and the muxer was not necessarily opened when the first
encoder started to produce data, the resulting packets were put into a
queue. As soon as the muxer was opened, the queue was flushed.

Change this to make the core wait with sending data until all encoders
are initialized. This has the advantage that we don't need to queue up
the packets.
2018-05-03 01:08:44 +03:00
wm4 f18c4175ad encode: remove old timestamp handling
This effectively makes --ocopyts the default. The --ocopyts option
itself is also removed, because it's redundant.
2018-05-03 01:08:44 +03:00
wm4 6c8362ef54 encode: rewrite half of it
The main change is that we wait with opening the muxer ("writing
headers") until we have data from all streams. This fixes race
conditions at init due to broken assumptions in the old code.

This also changes a lot of other stuff. I found and fixed a few API
violations (often things for which better mechanisms were invented, and
the old ones are not valid anymore). I try to get away from the public
mutex and shared fields in encode_lavc_context. For now it's still
needed for some timestamp-related fields, but most are gone. It also
removes some bad code duplication between audio and video paths.
2018-04-29 02:21:32 +03:00
wm4 20a1f250c6 encode: cosmetics
Mostly whitespace changes; some semantic preserving transformations.
2018-04-20 12:37:34 +02:00
wm4 9ee9313465 ao_alsa: actually report underruns to user
Print them as a warning.

Note that there may be some cases where it underruns, without being a
bad condition. This could possibly happen e.g. if the last chunk is
written, and then it resumes playback some time after that. Eventually I
want to add more code to avoid such spurious warnings.
2018-04-15 23:11:33 +03:00
wm4 66810c1550 ao_pulse: reduce requested device buffer size
Same deal as with the previous commit for ALSA.

Untested.
2018-04-15 23:11:33 +03:00
wm4 17f58455b0 ao_alsa: reduce requested buffer size
There is a dedicated thread for feeding audio to the ALSA API from a
buffer with a larger size. There is little reason to have such a large
device buffer.
2018-04-15 23:11:33 +03:00
wm4 401bd57d44 ao_alsa: add options for controlling period/buffer size 2018-04-15 23:11:33 +03:00
Jan Ekström 9de51b6032 ao_openal: document the muted↔gain conversion
This struck me as odd for a moment, so adding a comment.
2018-04-15 01:18:53 +03:00
LAGonauta 614ad62f89 ao/openal: Add option to set buffering characteristics
One can now set the number of buffers and the buffer size.
This can reduce the CPU usage and the total latency stays mostly the same.
As there are sync mechanisms the A/V sync continue intact and working.

It also modifies 6.1 channel order, as per OpenAL spec
and add AOPLAY_FINAL_CHUNK support
2018-04-15 00:57:01 +03:00
LAGonauta 567df04012 ao/openal: Add better sample format and channel layout selection
Also re-added floating-point support.
2018-04-15 00:57:01 +03:00
LAGonauta 8f82dc92aa ao/openal: Add OpenAL Soft extension to get the correct latency
OpenAL Soft's AL_SOFT_source_latency extension allows one to correctly
get the device output latency, facilitating the syncronization with
video.
Also added a simpler generic fallback that does not take into account
latency of the device.
2018-04-15 00:57:01 +03:00
LAGonauta dd357a7d53 ao/openal: Add support for direct channels output
Uses OpenAL Soft's AL_DIRECT_CHANNELS_SOFT extension and can be controlled through
a new CLI option, --openal-direct-channels.
This allows one to send the audio data direrctly to the desired channel without
effects applied.
2018-04-15 00:57:01 +03:00
LAGonauta abaab930f0 ao/openal: Add hardware mute support
While the volume is set on the listener, mute is set on the sound source.
Seemed easier that way.
2018-04-15 00:57:01 +03:00
LAGonauta c59ebbe399 ao/openal: Use only one source for audio output
Floating point audio not supported on this commit.
2018-04-15 00:57:01 +03:00
Tom Yan b0951d71f8 ao_opensles: let cfg_frames_per_buffer accept buffer size up to 0.5s at 192kHz 2018-04-05 04:35:49 +03:00
Tom Yan e3b3e28deb ao_opensles: remove useless cfg_sample_rate
We should always use the ao-neutral --audio-samplerate option.
2018-04-05 04:35:49 +03:00
Tom Yan 14b429de8d ao_opensles: bump device buffer size to 250ms
Although half (non-fast track on sink rate) or one-third (non-fast track not on sink rate) of the buffer size of the created AudioTrack instance as the SL Enqueue buffer size is basically enough for dropout-free playback, only using the full size can avoid stutter upon (re)start of playback.

Here are the various buffer sizes on different track/sink rate when on Bluetooth audio on Android O:

aptX @ 48kHz:
Sink rate: 48000 Hz
44100 Hz: 10632 frames (241.09 ms)
48000 Hz: 11544 frames (240.50 ms)
88200 Hz: 21216 frames (240.54 ms)
96000 Hz: 23088 frames (240.50 ms)
176400 Hz: 42384 frames (240.27 ms)
192000 Hz: 46128 frames (240.25 ms)

SBC/AAC/aptX @ 44.1kHz:
Sink rate: 44100 Hz
44100 Hz: 10776 frames (244.35 ms)
48000 Hz: 11748 frames (244.75 ms)
88200 Hz: 21552 frames (244.35 ms)
96000 Hz: 23448 frames (244.25 ms)
176400 Hz: 43056 frames (244.08 ms)
192000 Hz: 46848 frames (244.00 ms)

The above results were produced with the following code:

import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioTrack;

class AudioInfo {
    public static void main(String[] args) {
	int nosr = AudioTrack.getNativeOutputSampleRate(3);
	System.out.printf("Sink rate: %d Hz\n", nosr);

	int[] rates = {44100,48000,88200,96000,176400,192000};
	for (int rate: rates) {
	    AudioAttributes aa = new AudioAttributes.Builder().setFlags(256).build();
	    AudioFormat af = new AudioFormat.Builder().setSampleRate(rate).build();
	    AudioTrack at = new AudioTrack(aa, af, 4, 1, 0);
	    int sr = at.getSampleRate();
	    int bs = at.getBufferSizeInFrames();
	    float ms = bs * (float) 1000 / sr;
	    at.release();
	    System.out.printf("%d Hz: %d frames (%.2f ms)\n", sr, bs, ms);
	}
    }
}

Therefore bumping the device buffer size to 250ms.
2018-04-05 04:35:49 +03:00
Tom Yan 5a8c48fde2 ao_opensles: do one buffer only
Doing two buffers causes stutters upon (re)start of playback on Android O for all kinds of sinks.
2018-04-05 04:35:49 +03:00
Jan Ekström 59a04562b1 ao_opensles: re-flow interface/configuration retrieval
This manages to make the code more readable. Thanks to
MakeGho@IRCnet for the snippet on which this was based.
2018-03-24 03:43:57 +02:00
Aman Gupta aaa076b631 ao_opensles: fix audio sync using device latency extension 2018-03-23 01:00:01 +02:00
wm4 2f20168b0b ao_sdl: fix default buffer size
If you set desired.samples to 0, SDL will return a default buffer size
on obtained.samples. This was broken, because ceil_power_of_two(0)
returns 1. Since 0 is usually not considered a power of two, this is
probably correct, but we still want to set desired.samples to 0 in this
case.
2018-03-08 17:12:32 -08:00
wm4 f40e0cb0f2 ao: do not allow actual buffer size of 0
You can use --audio-buffer=0 to minimize the audio buffer size. But if
the AO reports no device buffer size (like e.g. ao_jack does), then the
buffer size is actually 0, and playback can never work properly.

Make it fallback to a size of 1, which is unlikely to work properly, but
you get what you asked for, instead of a freeze.
2018-03-08 17:12:32 -08:00
tomty89 013a8f75f3 ao_opensles: bump device buffer size to 200ms
While the soft buffer size is already by default 200ms, it is not enough to guarantee dropout-free playback on Bluetooth audio. Bumping the device buffer size to the same value seems to suffice.
2018-03-07 01:40:05 +02:00