avfilter/avf_avectorscope: add line drawing support
authorPaul B Mahol <onemda@gmail.com>
Tue, 5 Jan 2016 12:53:25 +0000 (13:53 +0100)
committerPaul B Mahol <onemda@gmail.com>
Tue, 5 Jan 2016 14:01:55 +0000 (15:01 +0100)
Signed-off-by: Paul B Mahol <onemda@gmail.com>
doc/filters.texi
libavfilter/avf_avectorscope.c

index 02ee9a6..a48ec3a 100644 (file)
@@ -13372,6 +13372,20 @@ Allowed range is @code{[0, 255]}.
 
 @item zoom
 Set the zoom factor. Default value is @code{1}. Allowed range is @code{[1, 10]}.
+
+@item draw
+Set the vectorscope drawing mode.
+
+Available values are:
+@table @samp
+@item dot
+Draw dot for each sample.
+
+@item line
+Draw line between previous and current sample.
+@end table
+
+Default value is @samp{dot}.
 @end table
 
 @subsection Examples
index 38dd97e..7f415fc 100644 (file)
@@ -40,15 +40,23 @@ enum VectorScopeMode {
     MODE_NB,
 };
 
+enum VectorScopeDraw {
+    DOT,
+    LINE,
+    DRAW_NB,
+};
+
 typedef struct AudioVectorScopeContext {
     const AVClass *class;
     AVFrame *outpicref;
     int w, h;
     int hw, hh;
     int mode;
+    int draw;
     int contrast[4];
     int fade[4];
     double zoom;
+    unsigned prev_x, prev_y;
     AVRational frame_rate;
 } AudioVectorScopeContext;
 
@@ -74,6 +82,9 @@ static const AVOption avectorscope_options[] = {
     { "bf", "set blue fade",      OFFSET(fade[2]), AV_OPT_TYPE_INT, {.i64=5},  0, 255, FLAGS },
     { "af", "set alpha fade",     OFFSET(fade[3]), AV_OPT_TYPE_INT, {.i64=5},  0, 255, FLAGS },
     { "zoom", "set zoom factor",  OFFSET(zoom), AV_OPT_TYPE_DOUBLE, {.dbl=1},  1, 10, FLAGS },
+    { "draw", "set draw mode", OFFSET(draw), AV_OPT_TYPE_INT, {.i64=DOT}, 0, DRAW_NB-1, FLAGS, "draw" },
+    { "dot",   "", 0, AV_OPT_TYPE_CONST, {.i64=DOT} , 0, 0, FLAGS, "draw" },
+    { "line",  "", 0, AV_OPT_TYPE_CONST, {.i64=LINE}, 0, 0, FLAGS, "draw" },
     { NULL }
 };
 
@@ -99,6 +110,32 @@ static void draw_dot(AudioVectorScopeContext *s, unsigned x, unsigned y)
     dst[3] = FFMIN(dst[3] + s->contrast[3], 255);
 }
 
+static void draw_line(AudioVectorScopeContext *s, int x0, int y0, int x1, int y1)
+{
+    int dx = FFABS(x1-x0), sx = x0 < x1 ? 1 : -1;
+    int dy = FFABS(y1-y0), sy = y0 < y1 ? 1 : -1;
+    int err = (dx>dy ? dx : -dy) / 2, e2;
+
+    for (;;) {
+        draw_dot(s, x0, y0);
+
+        if (x0 == x1 && y0 == y1)
+            break;
+
+        e2 = err;
+
+        if (e2 >-dx) {
+            err -= dy;
+            x0 += sx;
+        }
+
+        if (e2 < dy) {
+            err += dx;
+            y0 += sy;
+        }
+    }
+}
+
 static void fade(AudioVectorScopeContext *s)
 {
     const int linesize = s->outpicref->linesize[0];
@@ -168,8 +205,8 @@ static int config_output(AVFilterLink *outlink)
     outlink->sample_aspect_ratio = (AVRational){1,1};
     outlink->frame_rate = s->frame_rate;
 
-    s->hw = s->w / 2;
-    s->hh = s->h / 2;
+    s->prev_x = s->hw = s->w / 2;
+    s->prev_y = s->hh = s->h / 2;
 
     return 0;
 }
@@ -182,6 +219,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
     const int hw = s->hw;
     const int hh = s->hh;
     unsigned x, y;
+    unsigned prev_x = s->prev_x, prev_y = s->prev_y;
     const double zoom = s->zoom;
     int i;
 
@@ -223,7 +261,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
                 y = s->h - s->h * fabsf(cx + cy) * .7;
             }
 
-            draw_dot(s, x, y);
+            if (s->draw == DOT) {
+                draw_dot(s, x, y);
+            } else {
+                draw_line(s, x, y, prev_x, prev_y);
+            }
+            prev_x = x;
+            prev_y = y;
         }
         break;
     case AV_SAMPLE_FMT_FLT:
@@ -247,11 +291,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
                 y = s->h - s->h * fabsf(cx + cy) * .7;
             }
 
-            draw_dot(s, x, y);
+            if (s->draw == DOT) {
+                draw_dot(s, x, y);
+            } else {
+                draw_line(s, x, y, prev_x, prev_y);
+            }
+            prev_x = x;
+            prev_y = y;
         }
         break;
     }
 
+    s->prev_x = x, s->prev_y = y;
     av_frame_free(&insamples);
 
     return ff_filter_frame(outlink, av_frame_clone(s->outpicref));