summaryrefslogtreecommitdiff
path: root/libavfilter/af_asyncts.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavfilter/af_asyncts.c')
-rw-r--r--libavfilter/af_asyncts.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/libavfilter/af_asyncts.c b/libavfilter/af_asyncts.c
index 2e651ffca7..006839c671 100644
--- a/libavfilter/af_asyncts.c
+++ b/libavfilter/af_asyncts.c
@@ -35,6 +35,7 @@ typedef struct ASyncContext {
int min_delta; ///< pad/trim min threshold in samples
int first_frame; ///< 1 until filter_frame() has processed at least 1 frame with a pts != AV_NOPTS_VALUE
int64_t first_pts; ///< user-specified first expected pts, in samples
+ int comp; ///< current resample compensation
/* options */
int resample;
@@ -194,6 +195,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
int out_size, ret;
int64_t delta;
+ int64_t new_pts;
/* buffer data until we get the next timestamp */
if (s->pts == AV_NOPTS_VALUE || pts == AV_NOPTS_VALUE) {
@@ -220,10 +222,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
out_size = av_clipl_int32((int64_t)out_size + delta);
} else {
if (s->resample) {
- int comp = av_clip(delta, -s->max_comp, s->max_comp);
- av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
- avresample_set_compensation(s->avr, comp, inlink->sample_rate);
+ // adjust the compensation if delta is non-zero
+ int delay = get_delay(s);
+ int comp = s->comp + av_clip(delta * inlink->sample_rate / delay,
+ -s->max_comp, s->max_comp);
+ if (comp != s->comp) {
+ av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
+ if (avresample_set_compensation(s->avr, comp, inlink->sample_rate) == 0) {
+ s->comp = comp;
+ }
+ }
}
+ // adjust PTS to avoid monotonicity errors with input PTS jitter
+ pts -= delta;
delta = 0;
}
@@ -268,9 +279,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
/* drain any remaining buffered data */
avresample_read(s->avr, NULL, avresample_available(s->avr));
- s->pts = pts - avresample_get_delay(s->avr);
- ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
- buf->linesize[0], buf->nb_samples);
+ new_pts = pts - avresample_get_delay(s->avr);
+ /* check for s->pts monotonicity */
+ if (new_pts > s->pts) {
+ s->pts = new_pts;
+ ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
+ buf->linesize[0], buf->nb_samples);
+ } else {
+ av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
+ "whole buffer.\n");
+ ret = 0;
+ }
s->first_frame = 0;
fail: