X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faf_atempo.c;h=e4fc691abe614ee67c463a94820ebef29273a1c8;hb=c67d2a287502845baadf986a9c63e6117a25be3f;hp=52f15f2769b52cb876fe3e9b42366bb039a8df14;hpb=64425e005edf3bdd77c34c078c3e74ab5ecef557;p=ffmpeg diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c index 52f15f2769b..e4fc691abe6 100644 --- a/libavfilter/af_atempo.c +++ b/libavfilter/af_atempo.c @@ -103,6 +103,9 @@ typedef struct ATempoContext { // 1: output sample position int64_t position[2]; + // first input timestamp, all other timestamps are offset by this one + int64_t start_pts; + // sample format: enum AVSampleFormat format; @@ -149,12 +152,17 @@ typedef struct ATempoContext { uint64_t nsamples_out; } ATempoContext; +#define YAE_ATEMPO_MIN 0.5 +#define YAE_ATEMPO_MAX 100.0 + #define OFFSET(x) offsetof(ATempoContext, x) static const AVOption atempo_options[] = { { "tempo", "set tempo scale factor", - OFFSET(tempo), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0.5, 100.0, - AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM }, + OFFSET(tempo), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, + YAE_ATEMPO_MIN, + YAE_ATEMPO_MAX, + AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM }, { NULL } }; @@ -181,6 +189,7 @@ static void yae_clear(ATempoContext *atempo) atempo->nfrag = 0; atempo->state = YAE_LOAD_FRAGMENT; + atempo->start_pts = AV_NOPTS_VALUE; atempo->position[0] = 0; atempo->position[1] = 0; @@ -319,28 +328,14 @@ static int yae_reset(ATempoContext *atempo, return 0; } -static int yae_set_tempo(AVFilterContext *ctx, const char *arg_tempo) +static int yae_update(AVFilterContext *ctx) { const AudioFragment *prev; ATempoContext *atempo = ctx->priv; - char *tail = NULL; - double tempo = av_strtod(arg_tempo, &tail); - - if (tail && *tail) { - av_log(ctx, AV_LOG_ERROR, "Invalid tempo value '%s'\n", arg_tempo); - return AVERROR(EINVAL); - } - - if (tempo < 0.5 || tempo > 2.0) { - av_log(ctx, AV_LOG_ERROR, "Tempo value %f exceeds [0.5, 2.0] range\n", - tempo); - return AVERROR(EINVAL); - } prev = yae_prev_frag(atempo); atempo->origin[0] = prev->position[0] + atempo->window / 2; atempo->origin[1] = prev->position[1] + atempo->window / 2; - atempo->tempo = tempo; return 0; } @@ -1063,7 +1058,7 @@ static int push_samples(ATempoContext *atempo, atempo->dst_buffer->nb_samples = n_out; // adjust the PTS: - atempo->dst_buffer->pts = + atempo->dst_buffer->pts = atempo->start_pts + av_rescale_q(atempo->nsamples_out, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); @@ -1092,6 +1087,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *src_buffer) const uint8_t *src = src_buffer->data[0]; const uint8_t *src_end = src + n_in * atempo->stride; + if (atempo->start_pts == AV_NOPTS_VALUE) + atempo->start_pts = av_rescale_q(src_buffer->pts, + inlink->time_base, + outlink->time_base); + while (src < src_end) { if (!atempo->dst_buffer) { atempo->dst_buffer = ff_get_audio_buffer(outlink, n_out); @@ -1175,7 +1175,12 @@ static int process_command(AVFilterContext *ctx, int res_len, int flags) { - return !strcmp(cmd, "tempo") ? yae_set_tempo(ctx, arg) : AVERROR(ENOSYS); + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + return yae_update(ctx); } static const AVFilterPad atempo_inputs[] = {