mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 09:32:40 +00:00
audio: don't recreate AO if a filter changes the output format
Until recently, the AO was reinitialized strictly only on decoder format changes. But the commit for simplifying audio format negotiation removed this. Now the AO is recreated for any format change. This is sort of annoying if you change playback speed. The insertion/removal of af_scaletempo can change the sample format. For example, the acompressor filter will convert output to double, so toggling scaletempo will force the format back to float. This recreates the AO under the --gapless-audio=weak default. This likely affects a lot of other filters too. Work this around by allowing sample format changes, and keeping the current AO format in these cases. This is probably not a big problem. Most audio APIs force the output format to float anyway. This means you actually have to worry about what the default gapless mode does to your audio. If you start with a file that uses 8 bit per sample, and then continue playing a 24 bit FLAC, it will be converted down to 8 bit per sample. (Assuming they are played in a way that uses the gapless logic.)
This commit is contained in:
parent
9ee9313465
commit
4e7cbb7606
@ -1541,9 +1541,10 @@ Audio
|
||||
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.)
|
||||
The exact conditions under which the audio device is kept open is
|
||||
an implementation detail, and can change from version to version.
|
||||
Currently, the device is kept even if the sample format changes,
|
||||
but the sample formats are convertible.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -255,6 +255,33 @@ static char *audio_config_to_str_buf(char *buf, size_t buf_sz, int rate,
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Decide whether on a format change, we should reinit the AO.
|
||||
static bool keep_weak_gapless_format(struct mp_aframe *old, struct mp_aframe* new)
|
||||
{
|
||||
bool res = false;
|
||||
struct mp_aframe *new_mod = mp_aframe_new_ref(new);
|
||||
if (!new_mod)
|
||||
abort();
|
||||
|
||||
// If the sample formats are compatible (== libswresample generally can
|
||||
// convert them), keep the AO. On other changes, recreate it.
|
||||
|
||||
int old_fmt = mp_aframe_get_format(old);
|
||||
int new_fmt = mp_aframe_get_format(new);
|
||||
|
||||
if (af_format_conversion_score(old_fmt, new_fmt) == INT_MIN)
|
||||
goto done; // completely incompatible formats
|
||||
|
||||
if (!mp_aframe_set_format(new_mod, old_fmt))
|
||||
goto done;
|
||||
|
||||
res = mp_aframe_config_equals(old, new_mod);
|
||||
|
||||
done:
|
||||
talloc_free(new_mod);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void reinit_audio_filters_and_output(struct MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
@ -290,7 +317,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
|
||||
// previous one, keep the AO and don't reinit anything.
|
||||
// Strong gapless: always keep the AO
|
||||
if ((mpctx->ao_filter_fmt && mpctx->ao && opts->gapless_audio < 0 &&
|
||||
mp_aframe_config_equals(mpctx->ao_filter_fmt, out_fmt)) ||
|
||||
keep_weak_gapless_format(mpctx->ao_filter_fmt, out_fmt)) ||
|
||||
(mpctx->ao && opts->gapless_audio > 0))
|
||||
{
|
||||
mp_output_chain_set_ao(ao_c->filter, mpctx->ao);
|
||||
|
Loading…
Reference in New Issue
Block a user