On Thu, 13 Dec 2012 11:56:58 -0500, Justin Ruggles <[email protected]> wrote: > Currently it will do padding, but it does not properly handle > start-of-stream trimming as documented. > --- > libavfilter/af_asyncts.c | 64 +++++++++++++++++++++++++++++++++++++++------ > 1 files changed, 55 insertions(+), 9 deletions(-) > > diff --git a/libavfilter/af_asyncts.c b/libavfilter/af_asyncts.c > index 087692e..02dce5b 100644 > --- a/libavfilter/af_asyncts.c > +++ b/libavfilter/af_asyncts.c > @@ -33,6 +33,8 @@ typedef struct ASyncContext { > AVAudioResampleContext *avr; > int64_t pts; ///< timestamp in samples of the first sample in > fifo > 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 > > /* options */ > int resample; > @@ -50,7 +52,7 @@ static const AVOption options[] = { > { "min_delta", "Minimum difference between timestamps and audio data " > "(in seconds) to trigger padding/trimmin the data.", > OFFSET(min_delta_sec), AV_OPT_TYPE_FLOAT, { .dbl = 0.1 }, 0, INT_MAX, A }, > { "max_comp", "Maximum compensation in samples per second.", > OFFSET(max_comp), AV_OPT_TYPE_INT, { .i64 = 500 }, 0, INT_MAX, A }, > - { "first_pts", "Assume the first pts should be this value.", > OFFSET(pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, > INT64_MIN, INT64_MAX, A }, > + { "first_pts", "Assume the first pts should be this value.", > OFFSET(first_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, > INT64_MIN, INT64_MAX, A }, > { NULL }, > }; > > @@ -75,6 +77,9 @@ static int init(AVFilterContext *ctx, const char *args) > } > av_opt_free(s); > > + s->pts = AV_NOPTS_VALUE; > + s->first_frame = 1; > + > return 0; > } > > @@ -122,6 +127,20 @@ static int64_t get_delay(ASyncContext *s) > return avresample_available(s->avr) + avresample_get_delay(s->avr); > } > > +static void handle_trimming(AVFilterContext *ctx) > +{ > + ASyncContext *s = ctx->priv; > + > + if (s->pts < s->first_pts) { > + int delta = FFMIN(s->first_pts - s->pts, > avresample_available(s->avr)); > + av_log(ctx, AV_LOG_VERBOSE, "Trimming %d samples from start\n", > + delta); > + avresample_read(s->avr, NULL, delta); > + s->pts += delta; > + } else if (s->first_frame) > + s->pts = s->first_pts; > +} > + > static int request_frame(AVFilterLink *link) > { > AVFilterContext *ctx = link->src; > @@ -134,7 +153,11 @@ static int request_frame(AVFilterLink *link) > ret = ff_request_frame(ctx->inputs[0]); > > /* flush the fifo */ > - if (ret == AVERROR_EOF && (nb_samples = get_delay(s))) { > + if (ret == AVERROR_EOF) { > + if (s->first_pts != AV_NOPTS_VALUE) > + handle_trimming(ctx); > + > + if (nb_samples = get_delay(s)) { > AVFilterBufferRef *buf = ff_get_audio_buffer(link, AV_PERM_WRITE, > nb_samples); > if (!buf) > @@ -148,6 +171,7 @@ static int request_frame(AVFilterLink *link) > > buf->pts = s->pts; > return ff_filter_frame(link, buf); > + } > } > > return ret; > @@ -185,12 +209,18 @@ static int filter_frame(AVFilterLink *inlink, > AVFilterBufferRef *buf) > return write_to_fifo(s, buf); > } > > + if (s->first_pts != AV_NOPTS_VALUE) { > + handle_trimming(ctx); > + if (!avresample_available(s->avr)) > + return write_to_fifo(s, buf); > + } > + > /* when we have two timestamps, compute how many samples would we have > * to add/remove to get proper sync between data and timestamps */ > delta = pts - s->pts - get_delay(s); > out_size = avresample_available(s->avr); > > - if (labs(delta) > s->min_delta) { > + if (labs(delta) > s->min_delta || (s->first_frame && delta)) { > av_log(ctx, AV_LOG_VERBOSE, "Discontinuity - %"PRId64" samples.\n", > delta); > out_size = av_clipl_int32((int64_t)out_size + delta); > } else { > @@ -210,18 +240,33 @@ static int filter_frame(AVFilterLink *inlink, > AVFilterBufferRef *buf) > goto fail; > } > > - avresample_read(s->avr, buf_out->extended_data, out_size); > - buf_out->pts = s->pts; > + if (s->first_frame && delta > 0) { > + int ch; > + > + av_samples_set_silence(buf_out->extended_data, 0, delta, > + nb_channels, buf->format); > + > + for (ch = 0; ch < nb_channels; ch++) > + buf_out->extended_data[ch] += delta; > > - if (delta > 0) { > - av_samples_set_silence(buf_out->extended_data, out_size - delta, > - delta, nb_channels, buf->format); > + avresample_read(s->avr, buf_out->extended_data, out_size); > + > + for (ch = 0; ch < nb_channels; ch++) > + buf_out->extended_data[ch] -= delta; > + } else { > + avresample_read(s->avr, buf_out->extended_data, out_size); > + > + if (delta > 0) { > + av_samples_set_silence(buf_out->extended_data, out_size - > delta, > + delta, nb_channels, buf->format); > + } > } > + buf_out->pts = s->pts; > ret = ff_filter_frame(outlink, buf_out); > if (ret < 0) > goto fail; > s->got_output = 1; > - } else { > + } else if (avresample_available(s->avr)) { > av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping " > "whole buffer.\n"); > } > @@ -233,6 +278,7 @@ static int filter_frame(AVFilterLink *inlink, > AVFilterBufferRef *buf) > ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data, > buf->linesize[0], buf->audio->nb_samples); > > + s->first_frame = 0; > fail: > avfilter_unref_buffer(buf); >
Looks ok. -- Anton Khirnov _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
