]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/af_rubberband.c
avfilter:audio: fix shadowed AVFrame *out
[ffmpeg] / libavfilter / af_rubberband.c
index abd6483a75ff94be2bb9e07f323086f47eee7738..ded25449ddfe76b7ead36dc7d300b40887367d81 100644 (file)
@@ -175,29 +175,31 @@ static int request_frame(AVFilterLink *outlink)
     ret = ff_request_frame(ctx->inputs[0]);
 
     if (ret == AVERROR_EOF && !s->flushed) {
-        AVFrame *out = ff_get_audio_buffer(inlink, 1);
-        int nb_samples;
+        if (rubberband_available(s->rbs) > 0) {
+            AVFrame *out = ff_get_audio_buffer(inlink, 1);
+            int nb_samples;
 
-        if (!out)
-            return AVERROR(ENOMEM);
-
-        rubberband_process(s->rbs, (const float *const *)out->data, 1, 1);
-        av_frame_free(&out);
-        s->flushed = 1;
-        nb_samples = rubberband_available(s->rbs);
-
-        if (nb_samples > 0) {
-            out = ff_get_audio_buffer(inlink, nb_samples);
             if (!out)
                 return AVERROR(ENOMEM);
-            out->pts = av_rescale_q(s->nb_samples_out,
-                         (AVRational){ 1, outlink->sample_rate },
-                         outlink->time_base);
-            nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->data, nb_samples);
-            out->nb_samples = nb_samples;
-            ret = ff_filter_frame(outlink, out);
-            s->nb_samples_out += nb_samples;
+
+            rubberband_process(s->rbs, (const float *const *)out->data, 1, 1);
+            av_frame_free(&out);
+            nb_samples = rubberband_available(s->rbs);
+
+            if (nb_samples > 0) {
+                out = ff_get_audio_buffer(inlink, nb_samples);
+                if (!out)
+                    return AVERROR(ENOMEM);
+                out->pts = av_rescale_q(s->nb_samples_out,
+                             (AVRational){ 1, outlink->sample_rate },
+                             outlink->time_base);
+                nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->data, nb_samples);
+                out->nb_samples = nb_samples;
+                ret = ff_filter_frame(outlink, out);
+                s->nb_samples_out += nb_samples;
+            }
         }
+        s->flushed = 1;
         av_log(ctx, AV_LOG_DEBUG, "nb_samples_in %"PRId64" nb_samples_out %"PRId64"\n",
                                    s->nb_samples_in, s->nb_samples_out);
     }
@@ -205,6 +207,38 @@ static int request_frame(AVFilterLink *outlink)
     return ret;
 }
 
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    RubberBandContext *s = ctx->priv;
+
+    if (!strcmp(cmd, "tempo")) {
+        double arg;
+
+        sscanf(args, "%lf", &arg);
+        if (arg < 0.01 || arg > 100) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Tempo scale factor '%f' out of range\n", arg);
+            return AVERROR(EINVAL);
+        }
+        rubberband_set_time_ratio(s->rbs, 1. / arg);
+    }
+
+    if (!strcmp(cmd, "pitch")) {
+        double arg;
+
+        sscanf(args, "%lf", &arg);
+        if (arg < 0.01 || arg > 100) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Pitch scale factor '%f' out of range\n", arg);
+            return AVERROR(EINVAL);
+        }
+        rubberband_set_pitch_scale(s->rbs, arg);
+    }
+
+    return 0;
+}
+
 static const AVFilterPad rubberband_inputs[] = {
     {
         .name          = "default",
@@ -233,4 +267,5 @@ AVFilter ff_af_rubberband = {
     .uninit        = uninit,
     .inputs        = rubberband_inputs,
     .outputs       = rubberband_outputs,
+    .process_command = process_command,
 };