summaryrefslogtreecommitdiffstats
path: root/player/audio.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-09-21 12:48:30 +0200
committerwm4 <wm4@nowhere>2017-09-21 12:48:30 +0200
commitfdb300b983744c522f335ccf64e9788b78f86701 (patch)
treeabd10d97e8c6cb30e1621db8b67d709cbfaeb705 /player/audio.c
parent3a2d5e68acb2ac0f8b09b896907a692b1c48c6b3 (diff)
downloadmpv-fdb300b983744c522f335ccf64e9788b78f86701.tar.bz2
mpv-fdb300b983744c522f335ccf64e9788b78f86701.tar.xz
audio: make libaf derived code optional
This code could not be relicensed. The intention was to write new filter code (which could handle both audio and video), but that's a bit of work. Write some code that can do audio conversion (resampling, downmixing, etc.) without the old audio filter chain code in order to speed up the LGPL relicensing. If you build with --disable-libaf, nothing in audio/filter/* is compiled in. It breaks a few features, such as --volume, --af, pitch correction on speed changes, replaygain. Most likely this adds some bugs, even if --disable-libaf is not used. (How the fuck does EOF notification work again anyway?)
Diffstat (limited to 'player/audio.c')
-rw-r--r--player/audio.c310
1 files changed, 224 insertions, 86 deletions
diff --git a/player/audio.c b/player/audio.c
index 2a4c90dcc6..a26a7d1ff5 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -33,10 +33,10 @@
#include "common/common.h"
#include "osdep/timer.h"
-#include "audio/audio.h"
#include "audio/audio_buffer.h"
+#include "audio/aconverter.h"
+#include "audio/format.h"
#include "audio/decode/dec_audio.h"
-#include "audio/filter/af.h"
#include "audio/out/ao.h"
#include "demux/demux.h"
#include "video/decode/dec_video.h"
@@ -54,6 +54,11 @@ enum {
AD_STARVE = -6,
};
+#if HAVE_LIBAF
+
+#include "audio/audio.h"
+#include "audio/filter/af.h"
+
// Use pitch correction only for speed adjustments by the user, not minor sync
// correction ones.
static int get_speed_method(struct MPContext *mpctx)
@@ -180,7 +185,6 @@ void audio_update_volume(struct MPContext *mpctx)
if (opts->softvol_mute == 1)
gain = 0.0;
-#if HAVE_GPL
if (!af_control_any_rev(ao_c->af, AF_CONTROL_SET_VOLUME, &gain)) {
if (gain == 1.0)
return;
@@ -190,7 +194,6 @@ void audio_update_volume(struct MPContext *mpctx)
&& af_control_any_rev(ao_c->af, AF_CONTROL_SET_VOLUME, &gain)))
MP_ERR(mpctx, "No volume control available.\n");
}
-#endif
}
/* NOTE: Currently the balance code is seriously buggy: it always changes
@@ -238,7 +241,6 @@ static int recreate_audio_filters(struct MPContext *mpctx)
{
assert(mpctx->ao_chain);
-#if HAVE_GPL
struct af_stream *afs = mpctx->ao_chain->af;
if (afs->initialized < 1 && af_init(afs) < 0)
goto fail;
@@ -246,7 +248,6 @@ static int recreate_audio_filters(struct MPContext *mpctx)
recreate_speed_filters(mpctx);
if (afs->initialized < 1 && af_init(afs) < 0)
goto fail;
-#endif
if (mpctx->opts->softvol == SOFTVOL_NO)
MP_ERR(mpctx, "--softvol=no is not supported anymore.\n");
@@ -284,26 +285,40 @@ int reinit_audio_filters(struct MPContext *mpctx)
return 1;
}
+#else /* HAVE_LIBAV */
+
+void audio_update_volume(struct MPContext *mpctx) {}
+void audio_update_balance(struct MPContext *mpctx) {}
+int reinit_audio_filters(struct MPContext *mpctx) { return 0; }
+
+#endif /* else HAVE_LIBAF */
+
// Call this if opts->playback_speed or mpctx->speed_factor_* change.
void update_playback_speed(struct MPContext *mpctx)
{
mpctx->audio_speed = mpctx->opts->playback_speed * mpctx->speed_factor_a;
mpctx->video_speed = mpctx->opts->playback_speed * mpctx->speed_factor_v;
+#if HAVE_LIBAF
if (!mpctx->ao_chain || mpctx->ao_chain->af->initialized < 1)
return;
if (!update_speed_filters(mpctx))
recreate_audio_filters(mpctx);
+#endif
}
static void ao_chain_reset_state(struct ao_chain *ao_c)
{
ao_c->pts = MP_NOPTS_VALUE;
ao_c->pts_reset = false;
- talloc_free(ao_c->input_frame);
- ao_c->input_frame = NULL;
+ TA_FREEP(&ao_c->input_frame);
+ TA_FREEP(&ao_c->output_frame);
+#if HAVE_LIBAF
af_seek_reset(ao_c->af);
+#endif
+ if (ao_c->conv)
+ mp_aconverter_flush(ao_c->conv);
mp_audio_buffer_clear(ao_c->ao_buffer);
if (ao_c->audio_src)
@@ -350,9 +365,13 @@ static void ao_chain_uninit(struct ao_chain *ao_c)
if (ao_c->filter_src)
lavfi_set_connected(ao_c->filter_src, false);
+#if HAVE_LIBAF
af_destroy(ao_c->af);
+#endif
+ talloc_free(ao_c->conv);
talloc_free(ao_c->input_frame);
talloc_free(ao_c->input_format);
+ talloc_free(ao_c->filter_input_format);
talloc_free(ao_c->ao_buffer);
talloc_free(ao_c);
}
@@ -369,16 +388,17 @@ void uninit_audio_chain(struct MPContext *mpctx)
}
}
-static void get_ao_format(struct ao *ao, struct mp_audio *aformat)
+static char *audio_config_to_str_buf(char *buf, size_t buf_sz, int rate,
+ int format, struct mp_chmap channels)
{
- int samplerate;
- int format;
- struct mp_chmap channels;
- ao_get_format(ao, &samplerate, &format, &channels);
- *aformat = (struct mp_audio){0};
- mp_audio_set_format(aformat, format);
- mp_audio_set_channels(aformat, &channels);
- aformat->rate = samplerate;
+ char ch[128];
+ mp_chmap_to_str_buf(ch, sizeof(ch), &channels);
+ char *hr_ch = mp_chmap_to_str_hr(&channels);
+ if (strcmp(hr_ch, ch) != 0)
+ mp_snprintf_cat(ch, sizeof(ch), " (%s)", hr_ch);
+ snprintf(buf, buf_sz, "%dHz %s %dch %s", rate,
+ ch, channels.num, af_fmt_to_str(format));
+ return buf;
}
static void reinit_audio_filters_and_output(struct MPContext *mpctx)
@@ -387,7 +407,6 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
struct ao_chain *ao_c = mpctx->ao_chain;
assert(ao_c);
struct track *track = ao_c->track;
- struct af_stream *afs = ao_c->af;
if (!mp_aframe_config_is_valid(ao_c->input_format)) {
// We don't know the audio format yet - so configure it later as we're
@@ -403,24 +422,33 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
uninit_audio_out(mpctx);
}
+ TA_FREEP(&ao_c->output_frame);
+
+ int out_rate = 0;
+ int out_format = 0;
+ struct mp_chmap out_channels = {0};
+ if (mpctx->ao) {
+ ao_get_format(mpctx->ao, &out_rate, &out_format, &out_channels);
+ } else if (af_fmt_is_pcm(mp_aframe_get_format(ao_c->input_format))) {
+ out_rate = opts->force_srate;
+ out_format = opts->audio_output_format;
+ if (opts->audio_output_channels.num_chmaps == 1)
+ out_channels = opts->audio_output_channels.chmaps[0];
+ }
+
+#if HAVE_LIBAF
+ struct af_stream *afs = ao_c->af;
+
struct mp_audio in_format;
mp_audio_config_from_aframe(&in_format, ao_c->input_format);
if (mpctx->ao && mp_audio_config_equals(&in_format, &afs->input))
return;
afs->output = (struct mp_audio){0};
- if (mpctx->ao) {
- get_ao_format(mpctx->ao, &afs->output);
- } else if (af_fmt_is_pcm(mp_aframe_get_format(ao_c->input_format))) {
- afs->output.rate = opts->force_srate;
- mp_audio_set_format(&afs->output, opts->audio_output_format);
- if (opts->audio_output_channels.num_chmaps == 1) {
- mp_audio_set_channels(&afs->output,
- &opts->audio_output_channels.chmaps[0]);
- }
- }
+ afs->output.rate = out_rate;
+ mp_audio_set_format(&afs->output, out_format);
+ mp_audio_set_channels(&afs->output, &out_channels);
-#if HAVE_GPL
// filter input format: same as codec's output format:
afs->input = in_format;
@@ -432,9 +460,27 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
goto init_error;
}
+ out_rate = afs->output.rate;
+ out_format = afs->output.format;
+ out_channels = afs->output.channels;
+#else
+ if (mpctx->ao && ao_c->filter_input_format &&
+ mp_aframe_config_equals(ao_c->filter_input_format, ao_c->input_format))
+ return;
+
+ TA_FREEP(&ao_c->filter_input_format);
+
+ if (!out_rate)
+ out_rate = mp_aframe_get_rate(ao_c->input_format);
+ if (!out_format)
+ out_format = mp_aframe_get_format(ao_c->input_format);
+ if (!out_channels.num)
+ mp_aframe_get_chmap(ao_c->input_format, &out_channels);
+#endif
+
if (!mpctx->ao) {
int ao_flags = 0;
- bool spdif_fallback = af_fmt_is_spdif(afs->output.format) &&
+ bool spdif_fallback = af_fmt_is_spdif(out_format) &&
ao_c->spdif_passthrough;
if (opts->ao_null_fallback && !spdif_fallback)
@@ -446,30 +492,32 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
if (opts->audio_exclusive)
ao_flags |= AO_INIT_EXCLUSIVE;
- if (af_fmt_is_pcm(afs->output.format)) {
+ if (af_fmt_is_pcm(out_format)) {
if (!opts->audio_output_channels.set ||
opts->audio_output_channels.auto_safe)
ao_flags |= AO_INIT_SAFE_MULTICHANNEL_ONLY;
- mp_chmap_sel_list(&afs->output.channels,
+ mp_chmap_sel_list(&out_channels,
opts->audio_output_channels.chmaps,
opts->audio_output_channels.num_chmaps);
}
- mp_audio_set_channels(&afs->output, &afs->output.channels);
-
mpctx->ao = ao_init_best(mpctx->global, ao_flags, mp_wakeup_core_cb,
- mpctx, mpctx->encode_lavc_ctx, afs->output.rate,
- afs->output.format, afs->output.channels);
+ mpctx, mpctx->encode_lavc_ctx, out_rate,
+ out_format, out_channels);
ao_c->ao = mpctx->ao;
- struct mp_audio fmt = {0};
+ int ao_rate = 0;
+ int ao_format = 0;
+ struct mp_chmap ao_channels = {0};
if (mpctx->ao)
- get_ao_format(mpctx->ao, &fmt);
+ ao_get_format(mpctx->ao, &ao_rate, &ao_format, &ao_channels);
// Verify passthrough format was not changed.
- if (mpctx->ao && af_fmt_is_spdif(afs->output.format)) {
- if (!mp_audio_config_equals(&afs->output, &fmt)) {
+ if (mpctx->ao && af_fmt_is_spdif(out_format)) {
+ if (out_rate != ao_rate || out_format != ao_format ||
+ !mp_chmap_equals(&out_channels, &ao_channels))
+ {
MP_ERR(mpctx, "Passthrough format unsupported.\n");
ao_uninit(mpctx->ao);
mpctx->ao = NULL;
@@ -497,17 +545,36 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
goto init_error;
}
- mp_audio_buffer_reinit_fmt(ao_c->ao_buffer, fmt.format, &fmt.channels,
- fmt.rate);
- afs->output = fmt;
+ mp_audio_buffer_reinit_fmt(ao_c->ao_buffer, ao_format, &ao_channels,
+ ao_rate);
+
+#if HAVE_LIBAF
+ afs->output = (struct mp_audio){0};
+ afs->output.rate = ao_rate;
+ mp_audio_set_format(&afs->output, ao_format);
+ mp_audio_set_channels(&afs->output, &ao_channels);
if (!mp_audio_config_equals(&afs->output, &afs->filter_output))
afs->initialized = 0;
+#else
+ int in_rate = mp_aframe_get_rate(ao_c->input_format);
+ int in_format = mp_aframe_get_format(ao_c->input_format);
+ struct mp_chmap in_chmap = {0};
+ mp_aframe_get_chmap(ao_c->input_format, &in_chmap);
+ if (!mp_aconverter_reconfig(ao_c->conv, in_rate, in_format, in_chmap,
+ ao_rate, ao_format, ao_channels))
+ {
+ MP_ERR(mpctx, "Cannot convert audio data for output.\n");
+ goto init_error;
+ }
+ ao_c->filter_input_format = mp_aframe_new_ref(ao_c->input_format);
+#endif
- mpctx->ao_decoder_fmt = mp_aframe_create();
- mp_aframe_config_copy(mpctx->ao_decoder_fmt, ao_c->input_format);
+ mpctx->ao_decoder_fmt = mp_aframe_new_ref(ao_c->input_format);
+ char tmp[80];
MP_INFO(mpctx, "AO: [%s] %s\n", ao_get_name(mpctx->ao),
- mp_audio_config_to_str(&fmt));
+ audio_config_to_str_buf(tmp, sizeof(tmp), ao_rate, ao_format,
+ ao_channels));
MP_VERBOSE(mpctx, "AO: Description: %s\n", ao_get_description(mpctx->ao));
update_window_title(mpctx, true);
@@ -515,6 +582,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
opts->audio_wait_open > 0 ? mp_time_sec() + opts->audio_wait_open : 0;
}
+#if HAVE_LIBAF
if (recreate_audio_filters(mpctx) < 0)
goto init_error;
#endif
@@ -584,9 +652,13 @@ void reinit_audio_chain_src(struct MPContext *mpctx, struct track *track)
struct ao_chain *ao_c = talloc_zero(NULL, struct ao_chain);
mpctx->ao_chain = ao_c;
ao_c->log = mpctx->log;
+#if HAVE_LIBAF
ao_c->af = af_new(mpctx->global);
if (track && track->stream)
ao_c->af->replaygain_data = track->stream->codec->replaygain_data;
+#else
+ ao_c->conv = mp_aconverter_create(mpctx->global, mpctx->log, NULL);
+#endif
ao_c->spdif_passthrough = true;
ao_c->pts = MP_NOPTS_VALUE;
ao_c->ao_buffer = mp_audio_buffer_create(NULL);
@@ -628,16 +700,26 @@ double written_audio_pts(struct MPContext *mpctx)
if (!ao_c)
return MP_NOPTS_VALUE;
- if (ao_c->af->initialized < 1)
- return MP_NOPTS_VALUE;
-
// first calculate the end pts of audio that has been output by decoder
double a_pts = ao_c->pts;
if (a_pts == MP_NOPTS_VALUE)
return MP_NOPTS_VALUE;
// Data buffered in audio filters, measured in seconds of "missing" output
- double buffered_output = af_calc_delay(ao_c->af);
+ double buffered_output = 0;
+
+#if HAVE_LIBAF
+ if (ao_c->af->initialized < 1)
+ return MP_NOPTS_VALUE;
+
+ buffered_output += af_calc_delay(ao_c->af);
+#endif
+
+ if (ao_c->conv)
+ buffered_output += mp_aconverter_get_latency(ao_c->conv);
+
+ if (ao_c->output_frame)
+ buffered_output += mp_aframe_duration(ao_c->output_frame);
// Data that was ready for ao but was buffered because ao didn't fully
// accept everything to internal buffers yet
@@ -720,9 +802,12 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip)
if (mpctx->audio_status != STATUS_SYNCING)
return true;
- struct mp_audio out_format = {0};
- get_ao_format(mpctx->ao, &out_format);
- double play_samplerate = out_format.rate / mpctx->audio_speed;
+ int ao_rate;
+ int ao_format;
+ struct mp_chmap ao_channels;
+ ao_get_format(mpctx->ao, &ao_rate, &ao_format, &ao_channels);
+
+ double play_samplerate = ao_rate / mpctx->audio_speed;
if (!opts->initial_audio_sync) {
mpctx->audio_status = STATUS_FILLING;
@@ -784,25 +869,27 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip)
}
mpctx->audio_allow_second_chance_seek = false;
- int align = af_format_sample_alignment(out_format.format);
+ int align = af_format_sample_alignment(ao_format);
*skip = (int)(-ptsdiff * play_samplerate) / align * align;
return true;
}
-static bool copy_output(struct MPContext *mpctx, struct mp_audio_buffer *outbuf,
+static bool copy_output(struct MPContext *mpctx, struct ao_chain *ao_c,
int minsamples, double endpts, bool eof, bool *seteof)
{
- struct af_stream *afs = mpctx->ao_chain->af;
+ struct mp_audio_buffer *outbuf = ao_c->ao_buffer;
- while (mp_audio_buffer_samples(outbuf) < minsamples) {
- if (af_output_frame(afs, eof) < 0)
- return true; // error, stop doing stuff
+ int ao_rate;
+ int ao_format;
+ struct mp_chmap ao_channels;
+ ao_get_format(ao_c->ao, &ao_rate, &ao_format, &ao_channels);
+ while (mp_audio_buffer_samples(outbuf) < minsamples) {
int cursamples = mp_audio_buffer_samples(outbuf);
int maxsamples = INT_MAX;
if (endpts != MP_NOPTS_VALUE) {
- double rate = afs->output.rate / mpctx->audio_speed;
+ double rate = ao_rate / mpctx->audio_speed;
double curpts = written_audio_pts(mpctx);
if (curpts != MP_NOPTS_VALUE) {
double remaining =
@@ -811,24 +898,43 @@ static bool copy_output(struct MPContext *mpctx, struct mp_audio_buffer *outbuf,
}
}
- struct mp_audio *mpa = af_read_output_frame(afs);
- if (!mpa)
+ if (!ao_c->output_frame || !mp_aframe_get_size(ao_c->output_frame)) {
+ TA_FREEP(&ao_c->output_frame);
+#if HAVE_LIBAF
+ struct af_stream *afs = mpctx->ao_chain->af;
+ if (af_output_frame(afs, eof) < 0)
+ return true; // error, stop doing stuff
+ struct mp_audio *mpa = af_read_output_frame(afs);
+ ao_c->output_frame = mp_audio_to_aframe(mpa);
+ talloc_free(mpa);
+#else
+ if (eof)
+ mp_aconverter_write_input(ao_c->conv, NULL);
+ mp_aconverter_set_speed(ao_c->conv, mpctx->audio_speed);
+ bool got_eof;
+ ao_c->output_frame = mp_aconverter_read_output(ao_c->conv, &got_eof);
+#endif
+ }
+
+ if (!ao_c->output_frame)
return false; // out of data
- if (cursamples + mpa->samples > maxsamples) {
+ if (cursamples + mp_aframe_get_size(ao_c->output_frame) > maxsamples) {
if (cursamples < maxsamples) {
- struct mp_audio pre = *mpa;
- mp_audio_buffer_append(outbuf, mpa->planes,
+ uint8_t **data = mp_aframe_get_data_ro(ao_c->output_frame);
+ mp_audio_buffer_append(outbuf, (void **)data,
+ maxsamples - cursamples);
+ mp_aframe_skip_samples(ao_c->output_frame,
maxsamples - cursamples);
- mp_audio_skip_samples(mpa, pre.samples);
}
- af_unread_output_frame(afs, mpa);
*seteof = true;
return true;
}
- mp_audio_buffer_append(outbuf, mpa->planes, mpa->samples);
- talloc_free(mpa);
+ uint8_t **data = mp_aframe_get_data_ro(ao_c->output_frame);
+ mp_audio_buffer_append(outbuf, (void **)data,
+ mp_aframe_get_size(ao_c->output_frame));
+ TA_FREEP(&ao_c->output_frame);
}
return true;
}
@@ -869,9 +975,14 @@ static int filter_audio(struct MPContext *mpctx, struct mp_audio_buffer *outbuf,
int minsamples)
{
struct ao_chain *ao_c = mpctx->ao_chain;
+#if HAVE_LIBAF
struct af_stream *afs = ao_c->af;
if (afs->initialized < 1)
return AD_ERR;
+#else
+ if (!ao_c->filter_input_format)
+ return AD_ERR;
+#endif
MP_STATS(ao_c, "start audio");
@@ -882,7 +993,7 @@ static int filter_audio(struct MPContext *mpctx, struct mp_audio_buffer *outbuf,
while (1) {
res = 0;
- if (copy_output(mpctx, outbuf, minsamples, endpts, false, &eof))
+ if (copy_output(mpctx, ao_c, minsamples, endpts, false, &eof))
break;
res = decode_new_frame(ao_c);
@@ -892,41 +1003,58 @@ static int filter_audio(struct MPContext *mpctx, struct mp_audio_buffer *outbuf,
break;
if (res < 0) {
// drain filters first (especially for true EOF case)
- copy_output(mpctx, outbuf, minsamples, endpts, true, &eof);
+ copy_output(mpctx, ao_c, minsamples, endpts, true, &eof);
break;
}
// On format change, make sure to drain the filter chain.
+#if HAVE_LIBAF
struct mp_audio in_format;
mp_audio_config_from_aframe(&in_format, ao_c->input_format);
if (!mp_audio_config_equals(&afs->input, &in_format)) {
- copy_output(mpctx, outbuf, minsamples, endpts, true, &eof);
+ copy_output(mpctx, ao_c, minsamples, endpts, true, &eof);
+ res = AD_NEW_FMT;
+ break;
+ }
+#else
+ if (!mp_aframe_config_equals(ao_c->filter_input_format,
+ ao_c->input_format))
+ {
+ copy_output(mpctx, ao_c, minsamples, endpts, true, &eof);
res = AD_NEW_FMT;
break;
}
+#endif
- struct mp_audio *mpa = mp_audio_from_aframe(ao_c->input_frame);
- talloc_free(ao_c->input_frame);
- ao_c->input_frame = NULL;
- if (!mpa)
- abort();
- if (mpa->pts == MP_NOPTS_VALUE) {
+ double pts = mp_aframe_get_pts(ao_c->input_frame);
+ if (pts == MP_NOPTS_VALUE) {
ao_c->pts = MP_NOPTS_VALUE;
} else {
// Attempt to detect jumps in PTS. Even for the lowest sample rates
// and with worst container rounded timestamp, this should be a
// margin more than enough.
- double desync = mpa->pts - ao_c->pts;
+ double desync = pts - ao_c->pts;
if (ao_c->pts != MP_NOPTS_VALUE && fabs(desync) > 0.1) {
MP_WARN(ao_c, "Invalid audio PTS: %f -> %f\n",
- ao_c->pts, mpa->pts);
+ ao_c->pts, pts);
if (desync >= 5)
ao_c->pts_reset = true;
}
- ao_c->pts = mpa->pts + mpa->samples / (double)mpa->rate;
+ ao_c->pts = mp_aframe_end_pts(ao_c->input_frame);
}
+
+#if HAVE_LIBAF
+ struct mp_audio *mpa = mp_audio_from_aframe(ao_c->input_frame);
+ talloc_free(ao_c->input_frame);
+ ao_c->input_frame = NULL;
+ if (!mpa)
+ abort();
if (af_filter_frame(afs, mpa) < 0)
return AD_ERR;
+#else
+ if (mp_aconverter_write_input(ao_c->conv, ao_c->input_frame))
+ ao_c->input_frame = NULL;
+#endif
}
if (res == 0 && mp_audio_buffer_samples(outbuf) < minsamples && eof)
@@ -957,7 +1085,10 @@ void reload_audio_output(struct MPContext *mpctx)
ao_c->spdif_passthrough = true;
ao_c->spdif_failed = false;
d_audio->try_spdif = true;
+#if HAVE_LIBAF
ao_c->af->initialized = 0;
+#endif
+ TA_FREEP(&ao_c->filter_input_format);
if (!audio_init_best_codec(d_audio)) {
MP_ERR(mpctx, "Error reinitializing audio.\n");
error_on_track(mpctx, ao_c->track);
@@ -982,7 +1113,12 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
if (!ao_c)
return;
- if (ao_c->af->initialized < 1 || !mpctx->ao) {
+ bool is_initialized = !!ao_c->filter_input_format;
+#if HAVE_LIBAF
+ is_initialized = ao_c->af->initialized == 1;
+#endif
+
+ if (!is_initialized || !mpctx->ao) {
// Probe the initial audio format. Returns AD_OK (and does nothing) if
// the format is already known.
int r = AD_NO_PROGRESS;
@@ -1012,10 +1148,12 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
return;
}
- struct mp_audio out_format = {0};
- get_ao_format(mpctx->ao, &out_format);
- double play_samplerate = out_format.rate / mpctx->audio_speed;
- int align = af_format_sample_alignment(out_format.format);
+ int ao_rate;
+ int ao_format;
+ struct mp_chmap ao_channels;
+ ao_get_format(mpctx->ao, &ao_rate, &ao_format, &ao_channels);
+ double play_samplerate = ao_rate / mpctx->audio_speed;
+ int align = af_format_sample_alignment(ao_format);
// If audio is infinitely fast, somehow try keeping approximate A/V sync.
if (mpctx->audio_status == STATUS_PLAYING && ao_untimed(mpctx->ao) &&