diff options
author | wm4 <wm4@nowhere> | 2015-03-07 20:14:42 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-03-07 20:27:13 +0100 |
commit | b2099f55d2595259f5a0d1e6f2bee2f294556e31 (patch) | |
tree | be6a729fe89f150213852d66a643409ffb009477 /player | |
parent | 39537f64746d8e0ea0f828efee251fb84acdf11f (diff) | |
download | mpv-b2099f55d2595259f5a0d1e6f2bee2f294556e31.tar.bz2 mpv-b2099f55d2595259f5a0d1e6f2bee2f294556e31.tar.xz |
audio: make changing playback speed slightly more robust
Always use af_scaletempo if it's inserted, even if the option
--audio-pitch-correction=no is set.
Make sure all filters are reset on speed change. It's conceivable that
dynamic changes to the filter chain at runtime leave filters around
without resetting their speed parameters.
Also move the code to a separate function.
Diffstat (limited to 'player')
-rw-r--r-- | player/audio.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/player/audio.c b/player/audio.c index 96423151e7..f1dfe66784 100644 --- a/player/audio.c +++ b/player/audio.c @@ -60,47 +60,54 @@ static int try_filter(struct MPContext *mpctx, return 1; } -static int recreate_audio_filters(struct MPContext *mpctx) +static int update_playback_speed_filters(struct MPContext *mpctx) { - assert(mpctx->d_audio); - struct MPOpts *opts = mpctx->opts; + double speed = opts->playback_speed; struct af_stream *afs = mpctx->d_audio->afilter; - double speed = opts->playback_speed; + // Make sure only exactly one filter changes speed; resetting them all + // and setting 1 filter is the easiest way to achieve this. + af_control_all(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &(double){1}); + af_control_all(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &(double){1}); - if (speed != 1.0) { - int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE; - if (opts->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; - - // Compatibility: if the user uses --af=scaletempo, always use - // this filter to change speed. Don't insert a second "scaletempo" - // filter either. - if (!af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed)) - { - char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED - ? "scaletempo" : "lavrresample"; - if (try_filter(mpctx, filter, "playback-speed", NULL) < 0) - return -1; - // Try again. - if (!af_control_any_rev(afs, method, &speed)) - return -1; - } else { - method = AF_CONTROL_SET_PLAYBACK_SPEED; - } - } - } else { + if (speed == 1.0) + return af_remove_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; + + int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE; + if (opts->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; - // The filters could be inserted by the user (we don't remove them). - af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED, &speed); - af_control_any_rev(afs, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, &speed); + + char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED + ? "scaletempo" : "lavrresample"; + if (try_filter(mpctx, filter, "playback-speed", NULL) < 0) + return -1; + // Try again. + if (!af_control_any_rev(afs, method, &speed)) + return -1; } + return 0; +} + +static int recreate_audio_filters(struct MPContext *mpctx) +{ + assert(mpctx->d_audio); + + if (update_playback_speed_filters(mpctx) < 0) + return -1; + + 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; |