summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-04 21:31:53 +0100
committerwm4 <wm4@nowhere>2015-11-04 21:49:54 +0100
commit3108a3a0019a7c39c490413aa92ceea9e25a295f (patch)
tree171497f793fb9ed226665ac7a00f26c98d1f9006 /player
parent8f7cf9443f9336c7ca94301aa302612937c463ca (diff)
downloadmpv-3108a3a0019a7c39c490413aa92ceea9e25a295f.tar.bz2
mpv-3108a3a0019a7c39c490413aa92ceea9e25a295f.tar.xz
audio: do not require full audio chain reinit for speed changes
Actually, it didn't really require that before (most work was avoided), but some bits had to be run anyway. Separate the speed change into a light-weight function, which merely updates already created filters, and a heavy-weight one which messes with filter insertion. This also happens to fix the case where the filters would "forget" the current speed (force resampling, change speed, hit a volume control to force af_volume insertion - it will reset speed and desync). Since we now always run the light-weight function, remove the af_scaletempo verbose message that is printed on speed setting. Other than that, all setters are cheap.
Diffstat (limited to 'player')
-rw-r--r--player/audio.c123
1 files changed, 66 insertions, 57 deletions
diff --git a/player/audio.c b/player/audio.c
index 260c4fead4..0121dfb9e2 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -43,16 +43,23 @@
#include "core.h"
#include "command.h"
-static int update_playback_speed_filters(struct MPContext *mpctx)
+// Use pitch correction only for speed adjustments by the user, not minor sync
+// correction ones.
+static int get_speed_method(struct MPContext *mpctx)
+{
+ return mpctx->opts->pitch_correction && mpctx->opts->playback_speed != 1.0
+ ? AF_CONTROL_SET_PLAYBACK_SPEED : AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE;
+}
+
+// Try to reuse the existing filters to change playback speed. If it works,
+// return true; if filter recreation is needed, return false.
+static bool update_speed_filters(struct MPContext *mpctx)
{
- struct MPOpts *opts = mpctx->opts;
- double speed = mpctx->audio_speed;
struct af_stream *afs = mpctx->d_audio->afilter;
+ double speed = mpctx->audio_speed;
- // Use pitch correction only for speed adjustments by the user, not minor
- // sync correction ones.
- bool use_pitch_correction = opts->pitch_correction &&
- opts->playback_speed != 1.0;
+ if (afs->initialized < 1)
+ return false;
// Make sure only exactly one filter changes speed; resetting them all
// and setting 1 filter is the easiest way to achieve this.
@@ -60,54 +67,69 @@ static int update_playback_speed_filters(struct MPContext *mpctx)
af_control_all(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &(double){1});
if (speed == 1.0)
- return af_remove_by_label(afs, "playback-speed");
+ return !af_find_by_label(afs, "playback-speed");
// Compatibility: if the user uses --af=scaletempo, always use this
// filter to change speed. Don't insert a second filter (any) either.
if (!af_find_by_label(afs, "playback-speed") &&
af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed))
- return 0;
+ return true;
- int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE;
- if (use_pitch_correction)
- method = AF_CONTROL_SET_PLAYBACK_SPEED;
-
- if (!af_control_any_rev(afs, method, &speed)) {
- if (af_remove_by_label(afs, "playback-speed") < 0)
- return -1;
-
- char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED
- ? "scaletempo" : "lavrresample";
- if (af_add(afs, filter, "playback-speed", NULL) < 0)
- return -1;
- // Try again.
- if (!af_control_any_rev(afs, method, &speed))
- return -1;
- }
+ return !!af_control_any_rev(afs, get_speed_method(mpctx), &speed);
+}
- return 0;
+// Update speed, and insert/remove filters if necessary.
+static void recreate_speed_filters(struct MPContext *mpctx)
+{
+ struct af_stream *afs = mpctx->d_audio->afilter;
+
+ if (update_speed_filters(mpctx))
+ return;
+
+ if (af_remove_by_label(afs, "playback-speed") < 0)
+ goto fail;
+
+ if (mpctx->audio_speed == 1.0)
+ return;
+
+ int method = get_speed_method(mpctx);
+ char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED
+ ? "scaletempo" : "lavrresample";
+
+ if (!af_add(afs, filter, "playback-speed", NULL))
+ goto fail;
+
+ if (!update_speed_filters(mpctx))
+ goto fail;
+
+ return;
+
+fail:
+ mpctx->opts->playback_speed = 1.0;
+ mpctx->speed_factor_a = 1.0;
+ mpctx->audio_speed = 1.0;
+ mp_notify(mpctx, MP_EVENT_CHANGE_ALL, NULL);
}
static int recreate_audio_filters(struct MPContext *mpctx)
{
assert(mpctx->d_audio);
- if (update_playback_speed_filters(mpctx) < 0) {
- mpctx->opts->playback_speed = 1.0;
- mpctx->speed_factor_a = 1.0;
- mpctx->audio_speed = 1.0;
- mp_notify(mpctx, MP_EVENT_CHANGE_ALL, NULL);
- }
-
struct af_stream *afs = mpctx->d_audio->afilter;
- if (afs->initialized < 1 && af_init(afs) < 0) {
- MP_ERR(mpctx, "Couldn't find matching filter/ao format!\n");
- return -1;
- }
+ if (afs->initialized < 1 && af_init(afs) < 0)
+ goto fail;
+
+ recreate_speed_filters(mpctx);
+ if (afs->initialized < 1 && af_init(afs) < 0)
+ goto fail;
mixer_reinit_audio(mpctx->mixer, mpctx->ao, afs);
return 0;
+
+fail:
+ MP_ERR(mpctx, "Couldn't find matching filter/ao format!\n");
+ return -1;
}
int reinit_audio_filters(struct MPContext *mpctx)
@@ -117,33 +139,20 @@ int reinit_audio_filters(struct MPContext *mpctx)
return 0;
af_uninit(mpctx->d_audio->afilter);
- if (af_init(mpctx->d_audio->afilter) < 0)
- return -1;
- if (recreate_audio_filters(mpctx) < 0)
- return -1;
-
- return 1;
+ return recreate_audio_filters(mpctx) < 0 ? -1 : 1;
}
-// Call this if opts->playback_speed or mpctx->speed_correction changes.
+// Call this if opts->playback_speed or mpctx->speed_factor_* change.
void update_playback_speed(struct MPContext *mpctx)
{
- struct MPOpts *opts = mpctx->opts;
-
- double old_speed_factor_a = mpctx->speed_factor_a;
- double old_audio_speed = mpctx->audio_speed;
-
- mpctx->audio_speed = opts->playback_speed * mpctx->speed_factor_a;
- mpctx->video_speed = opts->playback_speed * mpctx->speed_factor_v;
-
- if (mpctx->speed_factor_a == old_speed_factor_a &&
- mpctx->audio_speed == old_audio_speed)
- return;
+ mpctx->audio_speed = mpctx->opts->playback_speed * mpctx->speed_factor_a;
+ mpctx->video_speed = mpctx->opts->playback_speed * mpctx->speed_factor_v;
- if (!mpctx->d_audio || mpctx->d_audio->afilter->initialized < 1)
+ if (!mpctx->d_audio)
return;
- recreate_audio_filters(mpctx);
+ if (!update_speed_filters(mpctx))
+ recreate_audio_filters(mpctx);
}
void reset_audio_state(struct MPContext *mpctx)