mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
72ee9bb56c
commit
07aba86b37
|
@ -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=<string>``
|
||||
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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue