From 07aba86b37887c0aef7ea90af250fcf19062369b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 15 Aug 2014 23:52:42 +0200 Subject: audio: add a mode to insert silence on severe A/V desync This is probably a stupid idea, but it can't be denied that this actually allows playing video without larger desync, even if video is too slow. --- DOCS/man/options.rst | 5 +++++ options/options.c | 2 ++ options/options.h | 1 + player/audio.c | 21 +++++++++++++++++---- player/core.h | 2 ++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 7839480918..fa4dcd3b8b 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -967,6 +967,11 @@ Audio Set the step size of mixer volume changes in percent of the full range (default: 3). +``--audiodrop`` + If video is by more than 500ms behind, insert 500ms of silence, to make up + for audio getting ahead. Might help if video decoding is too slow beyond + help. + ``--volume-restore-data=`` Used internally for use by playback resume (e.g. with ``quit_watch_later``). Restoring value has to be done carefully, because different AOs as well as diff --git a/options/options.c b/options/options.c index af294a7709..58e8d9dec4 100644 --- a/options/options.c +++ b/options/options.c @@ -462,6 +462,8 @@ const m_option_t mp_opts[] = { {"decoder", 2}, {"decoder+vo", 3})), + OPT_FLAG("audiodrop", insert_silence, 0), + OPT_FLAG("untimed", untimed, M_OPT_FIXED), OPT_STRING("stream-capture", stream_capture, M_OPT_FIXED), diff --git a/options/options.h b/options/options.h index 5f59fa42c6..9b48a0162e 100644 --- a/options/options.h +++ b/options/options.h @@ -137,6 +137,7 @@ typedef struct MPOpts { float default_max_pts_correction; int autosync; int frame_dropping; + int insert_silence; int term_osd; int term_osd_bar; char *term_osd_bar_chars; diff --git a/player/audio.c b/player/audio.c index abb81f987c..3a691fed09 100644 --- a/player/audio.c +++ b/player/audio.c @@ -384,6 +384,10 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return; // try again next iteration } + struct mp_audio out_format = {0}; + ao_get_format(mpctx->ao, &out_format); + double play_samplerate = out_format.rate / opts->playback_speed; + // If audio is infinitely fast, somehow try keeping approximate A/V sync. if (mpctx->audio_status == STATUS_PLAYING && ao_untimed(mpctx->ao) && mpctx->video_status != STATUS_EOF && mpctx->delay > 0) @@ -402,6 +406,19 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) playsize = MPMAX(1, playsize + skip); // silence will be prepended } + if (opts->insert_silence) { + float S = 0.5; + if (!mpctx->paused && mpctx->audio_status == STATUS_PLAYING && + mpctx->last_av_difference - mpctx->insert_silence > S) + mpctx->insert_silence += S; + + if (mpctx->insert_silence > 0) { + int samples = MPMIN(playsize, play_samplerate * mpctx->insert_silence); + mp_audio_buffer_prepend_silence(mpctx->ao_buffer, samples); + mpctx->insert_silence -= samples / play_samplerate; + } + } + int status = AD_OK; if (playsize > mp_audio_buffer_samples(mpctx->ao_buffer)) { status = audio_decode(d_audio, mpctx->ao_buffer, playsize); @@ -470,10 +487,6 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) bool partial_fill = false; int playflags = 0; - struct mp_audio out_format = {0}; - ao_get_format(mpctx->ao, &out_format); - double play_samplerate = out_format.rate / opts->playback_speed; - if (endpts != MP_NOPTS_VALUE) { double samples = (endpts - written_audio_pts(mpctx) - mpctx->audio_delay) * play_samplerate; diff --git a/player/core.h b/player/core.h index 594f105668..2530e8acd2 100644 --- a/player/core.h +++ b/player/core.h @@ -260,6 +260,8 @@ typedef struct MPContext { double delay; // AV sync: time until next frame should be shown double time_frame; + // Optional/additional AV sync compensation if video is too slow. + double insert_silence; // Set to true some time after a new frame has been shown, and it turns out // that this frame was the last one before video ends. bool playing_last_frame; -- cgit v1.2.3