diff options
-rw-r--r-- | DOCS/man/en/options.rst | 43 | ||||
-rw-r--r-- | options/options.c | 5 | ||||
-rw-r--r-- | player/audio.c | 12 | ||||
-rw-r--r-- | player/core.h | 1 | ||||
-rw-r--r-- | player/loadfile.c | 2 |
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) |