summaryrefslogtreecommitdiffstats
path: root/player/audio.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-08-10 18:40:16 +0200
committerwm4 <wm4@nowhere>2015-08-10 18:40:16 +0200
commitfedaad8250b9c9e262da3cda2114ccf5b62703a3 (patch)
treeffd35bcfbb0b50f828ecb7e78756478248311395 /player/audio.c
parent3d1cc17ab27b98294f5710e69250e95347d84598 (diff)
downloadmpv-fedaad8250b9c9e262da3cda2114ccf5b62703a3.tar.bz2
mpv-fedaad8250b9c9e262da3cda2114ccf5b62703a3.tar.xz
player: separate controls for user and video controlled speed
For video sync, we want separate playback speed controls for user- requested speed and the "correction" speed for video timing. Further, we use this separation to make sure only a resampler is inserted if playback speed is only changed for video sync correction. As of this commit, this is basically inactive code. It's just preparation for the video sync code (the following commit).
Diffstat (limited to 'player/audio.c')
-rw-r--r--player/audio.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/player/audio.c b/player/audio.c
index 5b19e2fc0c..ab4e50b1b9 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -45,9 +45,14 @@
static int update_playback_speed_filters(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
- double speed = opts->playback_speed;
+ double speed = mpctx->audio_speed;
struct af_stream *afs = mpctx->d_audio->afilter;
+ // 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;
+
// 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});
@@ -63,7 +68,7 @@ static int update_playback_speed_filters(struct MPContext *mpctx)
return 0;
int method = AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE;
- if (opts->pitch_correction)
+ if (use_pitch_correction)
method = AF_CONTROL_SET_PLAYBACK_SPEED;
if (!af_control_any_rev(afs, method, &speed)) {
@@ -88,6 +93,8 @@ static int recreate_audio_filters(struct MPContext *mpctx)
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);
}
@@ -117,11 +124,20 @@ int reinit_audio_filters(struct MPContext *mpctx)
return 1;
}
-void set_playback_speed(struct MPContext *mpctx, double new_speed)
+// Call this if opts->playback_speed or mpctx->speed_correction changes.
+void update_playback_speed(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
- opts->playback_speed = new_speed;
+ 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;
if (!mpctx->d_audio || mpctx->d_audio->afilter->initialized < 1)
return;
@@ -300,7 +316,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
if (recreate_audio_filters(mpctx) < 0)
goto init_error;
- set_playback_speed(mpctx, opts->playback_speed);
+ update_playback_speed(mpctx);
return;
@@ -349,9 +365,9 @@ double written_audio_pts(struct MPContext *mpctx)
// accept everything to internal buffers yet
buffered_output += mp_audio_buffer_seconds(mpctx->ao_buffer);
- // Filters divide audio length by playback_speed, so multiply by it
+ // Filters divide audio length by audio_speed, so multiply by it
// to get the length in original units without speedup or slowdown
- a_pts -= buffered_output * mpctx->opts->playback_speed;
+ a_pts -= buffered_output * mpctx->audio_speed;
return a_pts +
get_track_video_offset(mpctx, mpctx->current_track[0][STREAM_AUDIO]);
@@ -363,7 +379,7 @@ double playing_audio_pts(struct MPContext *mpctx)
double pts = written_audio_pts(mpctx);
if (pts == MP_NOPTS_VALUE || !mpctx->ao)
return pts;
- return pts - mpctx->opts->playback_speed * ao_get_delay(mpctx->ao);
+ return pts - mpctx->audio_speed * ao_get_delay(mpctx->ao);
}
static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags)
@@ -378,7 +394,7 @@ static int write_to_ao(struct MPContext *mpctx, struct mp_audio *data, int flags
#endif
if (data->samples == 0)
return 0;
- double real_samplerate = out_format.rate / mpctx->opts->playback_speed;
+ double real_samplerate = out_format.rate / mpctx->audio_speed;
int played = ao_play(mpctx->ao, data->planes, data->samples, flags);
assert(played <= data->samples);
if (played > 0) {
@@ -406,7 +422,7 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip)
struct mp_audio out_format = {0};
ao_get_format(mpctx->ao, &out_format);
- double play_samplerate = out_format.rate / opts->playback_speed;
+ double play_samplerate = out_format.rate / mpctx->audio_speed;
if (!opts->initial_audio_sync) {
mpctx->audio_status = STATUS_FILLING;
@@ -483,7 +499,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
struct mp_audio out_format = {0};
ao_get_format(mpctx->ao, &out_format);
- double play_samplerate = out_format.rate / opts->playback_speed;
+ double play_samplerate = out_format.rate / mpctx->audio_speed;
// If audio is infinitely fast, somehow try keeping approximate A/V sync.
if (mpctx->audio_status == STATUS_PLAYING && ao_untimed(mpctx->ao) &&