mirror of
https://github.com/mpv-player/mpv
synced 2025-02-20 23:07:02 +00:00
audio: add a "weak" gapless mode, and make it default
Basically, this allows gapless playback with similar files (including the ordered chapter case), while still being robust in general. The implementation is quite simplistic on purpose, in order to avoid all the weird corner cases that can occur when creating the filter chain. The consequence is that it might do not-gapless playback in more cases when needed, but if that bothers you, you still can use the normal gapless mode. Just using "--gapless-audio" or "--gapless-audio=yes" selects the old mode.
This commit is contained in:
parent
da89af1076
commit
3e2f16a89e
@ -901,26 +901,37 @@ OPTIONS
|
||||
Adjust the gamma of the video signal (default: 0). Not supported by all
|
||||
video output drivers.
|
||||
|
||||
``--gapless-audio``
|
||||
``--gapless-audio=<no|yes|weak``
|
||||
Try to play consecutive audio files with no silence or disruption at the
|
||||
point of file change. This feature is implemented in a simple manner and
|
||||
relies on audio output device buffering to continue playback while moving
|
||||
from one file to another. If playback of the new file starts slowly, for
|
||||
example because it is played from a remote network location or because you
|
||||
have specified cache settings that require time for the initial cache
|
||||
fill, then the buffered audio may run out before playback of the new file
|
||||
can start.
|
||||
point of file change. Default: ``weak``.
|
||||
|
||||
:no: Disable gapless audio.
|
||||
:yes: The audio device is opened using parameters chosen according to the
|
||||
first file played and is then kept open for gapless playback. This
|
||||
means that if the first file for example has a low sample rate, then
|
||||
the following files may get resampled to the same low sample rate,
|
||||
resulting in reduced sound quality. If you play files with different
|
||||
parameters, consider using options such as ``--audio-samplerate``
|
||||
and ``--audio-format`` to explicitly select what the shared output
|
||||
format will be.
|
||||
:weak: Normally, the audio device is kept open (using the format it was
|
||||
first initialized with). If the audio format the decoder output
|
||||
changes, the audio device is closed and reopened. This means that
|
||||
you will normally get gapless audio with files that were encoded
|
||||
using the same settings, but might not be gapless in other cases.
|
||||
(Unlike with ``yes``, you don't have to worry about corner cases
|
||||
like the first file setting a very low quality output format, and
|
||||
ruining the playback of higher quality files that follow.)
|
||||
|
||||
.. note::
|
||||
|
||||
The audio device is opened using parameters chosen according to the
|
||||
first file played and is then kept open for gapless playback. This means
|
||||
that if the first file for example has a low sample rate, then the
|
||||
following files may get resampled to the same low sample rate, resulting
|
||||
in reduced sound quality. If you play files with different parameters,
|
||||
consider using options such as ``--audio-samplerate`` and
|
||||
``--audio-format`` to explicitly select what the shared output format
|
||||
will be.
|
||||
This feature is implemented in a simple manner and relies on audio
|
||||
output device buffering to continue playback while moving from one file
|
||||
to another. If playback of the new file starts slowly, for example
|
||||
because it is played from a remote network location or because you have
|
||||
specified cache settings that require time for the initial cache fill,
|
||||
then the buffered audio may run out before playback of the new file
|
||||
can start.
|
||||
|
||||
``--geometry=<[W[xH]][+-x+-y]>``, ``--geometry=<x:y>``
|
||||
Adjust the initial window position or size. ``W`` and ``H`` set the window
|
||||
|
@ -460,7 +460,10 @@ const m_option_t mp_opts[] = {
|
||||
{"no", 0},
|
||||
{"yes", 1}, {"", 1})),
|
||||
OPT_STRING("volume-restore-data", mixer_restore_volume_data, 0),
|
||||
OPT_FLAG("gapless-audio", gapless_audio, M_OPT_FIXED),
|
||||
OPT_CHOICE("gapless-audio", gapless_audio, M_OPT_FIXED | M_OPT_OPTIONAL_PARAM,
|
||||
({"no", 0},
|
||||
{"yes", 1}, {"", 1},
|
||||
{"weak", -1})),
|
||||
|
||||
OPT_GEOMETRY("geometry", vo.geometry, 0),
|
||||
OPT_SIZE_BOX("autofit", vo.autofit, 0),
|
||||
|
@ -129,6 +129,13 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
||||
struct mp_audio in_format;
|
||||
mp_audio_buffer_get_format(mpctx->d_audio->decode_buffer, &in_format);
|
||||
|
||||
if (mpctx->ao_decoder_fmt && (mpctx->initialized_flags & INITIALIZED_AO) &&
|
||||
!mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format) &&
|
||||
opts->gapless_audio < 0)
|
||||
{
|
||||
uninit_player(mpctx, INITIALIZED_AO);
|
||||
}
|
||||
|
||||
int ao_srate = opts->force_srate;
|
||||
int ao_format = opts->audio_output_format;
|
||||
struct mp_chmap ao_channels = {0};
|
||||
@ -174,6 +181,9 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
||||
mpctx->ao_buffer = mp_audio_buffer_create(ao);
|
||||
mp_audio_buffer_reinit(mpctx->ao_buffer, &fmt);
|
||||
|
||||
mpctx->ao_decoder_fmt = talloc(NULL, struct mp_audio);
|
||||
*mpctx->ao_decoder_fmt = in_format;
|
||||
|
||||
char *s = mp_audio_config_to_str(&fmt);
|
||||
MP_INFO(mpctx, "AO: [%s] %s\n", ao_get_name(ao), s);
|
||||
talloc_free(s);
|
||||
@ -413,7 +423,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
|
||||
* implementation would require draining buffered old-format audio
|
||||
* while displaying video, then doing the output format switch.
|
||||
*/
|
||||
if (!mpctx->opts->gapless_audio)
|
||||
if (mpctx->opts->gapless_audio < 1)
|
||||
uninit_player(mpctx, INITIALIZED_AO);
|
||||
reinit_audio_chain(mpctx);
|
||||
return -1;
|
||||
|
@ -218,6 +218,7 @@ typedef struct MPContext {
|
||||
struct mixer *mixer;
|
||||
struct ao *ao;
|
||||
double ao_pts;
|
||||
struct mp_audio *ao_decoder_fmt; // for weak gapless audio check
|
||||
struct mp_audio_buffer *ao_buffer; // queued audio; passed to ao_play() later
|
||||
|
||||
struct vo *video_out;
|
||||
|
@ -179,6 +179,8 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
|
||||
ao_uninit(ao);
|
||||
}
|
||||
mpctx->ao = NULL;
|
||||
talloc_free(mpctx->ao_decoder_fmt);
|
||||
mpctx->ao_decoder_fmt = NULL;
|
||||
}
|
||||
|
||||
if (mask & INITIALIZED_PLAYBACK)
|
||||
|
Loading…
Reference in New Issue
Block a user