summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/options.rst43
-rw-r--r--options/options.c5
-rw-r--r--player/audio.c12
-rw-r--r--player/core.h1
-rw-r--r--player/loadfile.c2
5 files changed, 45 insertions, 18 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index e64c726a45..ec5061c4de 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -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
diff --git a/options/options.c b/options/options.c
index 8f071345d5..e1e8cdb99e 100644
--- a/options/options.c
+++ b/options/options.c
@@ -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),
diff --git a/player/audio.c b/player/audio.c
index 1070270dda..e0c6ca9a0c 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -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;
diff --git a/player/core.h b/player/core.h
index 5f4789d267..e3d84f4ed9 100644
--- a/player/core.h
+++ b/player/core.h
@@ -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;
diff --git a/player/loadfile.c b/player/loadfile.c
index d79e82911c..cc65aedd6d 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -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)