summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2018-03-23 19:02:51 +0100
committerPaul B Mahol <onemda@gmail.com>2018-03-23 19:02:51 +0100
commita8c2d375ca68b7f001564ced14d8ac0757f53a29 (patch)
tree99a3f8d4bfce4d64644c21949171d0192aa6f86b
parentfe0fdc51b56e061ee00ef237c218e18b99468878 (diff)
avfilter/avf_showwaves: add draw mode which controls how single sample is drawn
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r--doc/filters.texi14
-rw-r--r--libavfilter/avf_showwaves.c119
2 files changed, 115 insertions, 18 deletions
diff --git a/doc/filters.texi b/doc/filters.texi
index 870c50441b..421b5f6cd2 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -20033,6 +20033,20 @@ Cubic root.
@end table
Default is linear.
+
+@item draw
+Set the draw mode. This is mostly useful to set for high @var{n}.
+
+Available values are:
+@table @samp
+@item scale
+Scale pixel values for each drawn sample.
+
+@item full
+Draw every sample directly.
+@end table
+
+Default vlaue is @code{scale}.
@end table
@subsection Examples
diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
index 0866967984..bb7f4ea87e 100644
--- a/libavfilter/avf_showwaves.c
+++ b/libavfilter/avf_showwaves.c
@@ -50,6 +50,12 @@ enum ShowWavesScale {
SCALE_NB,
};
+enum ShowWavesDrawMode {
+ DRAW_SCALE,
+ DRAW_FULL,
+ DRAW_NB,
+};
+
struct frame_node {
AVFrame *frame;
struct frame_node *next;
@@ -68,6 +74,7 @@ typedef struct ShowWavesContext {
int sample_count_mod;
int mode; ///< ShowWavesMode
int scale; ///< ShowWavesScale
+ int draw_mode; ///< ShowWavesDrawMode
int split_channels;
uint8_t *fg;
@@ -104,6 +111,9 @@ static const AVOption showwaves_options[] = {
{ "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_LOG}, .flags=FLAGS, .unit="scale"},
{ "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_SQRT}, .flags=FLAGS, .unit="scale"},
{ "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_CBRT}, .flags=FLAGS, .unit="scale"},
+ { "draw", "set draw mode", OFFSET(draw_mode), AV_OPT_TYPE_INT, {.i64 = DRAW_SCALE}, 0, DRAW_NB-1, FLAGS, .unit="draw" },
+ { "scale", "scale pixel values for each drawn sample", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_SCALE}, .flags=FLAGS, .unit="draw"},
+ { "full", "draw every pixel for sample directly", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_FULL}, .flags=FLAGS, .unit="draw"},
{ NULL }
};
@@ -202,9 +212,9 @@ static int get_cbrt_h2(int16_t sample, int height)
return cbrt(FFABS(sample)) * height / cbrt(INT16_MAX);
}
-static void draw_sample_point_rgba(uint8_t *buf, int height, int linesize,
- int16_t *prev_y,
- const uint8_t color[4], int h)
+static void draw_sample_point_rgba_scale(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
{
if (h >= 0 && h < height) {
buf[h * linesize + 0] += color[0];
@@ -214,9 +224,21 @@ static void draw_sample_point_rgba(uint8_t *buf, int height, int linesize,
}
}
-static void draw_sample_line_rgba(uint8_t *buf, int height, int linesize,
- int16_t *prev_y,
- const uint8_t color[4], int h)
+static void draw_sample_point_rgba_full(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
+{
+ if (h >= 0 && h < height) {
+ buf[h * linesize + 0] = color[0];
+ buf[h * linesize + 1] = color[1];
+ buf[h * linesize + 2] = color[2];
+ buf[h * linesize + 3] = color[3];
+ }
+}
+
+static void draw_sample_line_rgba_scale(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
{
int k;
int start = height/2;
@@ -231,9 +253,26 @@ static void draw_sample_line_rgba(uint8_t *buf, int height, int linesize,
}
}
-static void draw_sample_p2p_rgba(uint8_t *buf, int height, int linesize,
- int16_t *prev_y,
- const uint8_t color[4], int h)
+static void draw_sample_line_rgba_full(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
+{
+ int k;
+ int start = height/2;
+ int end = av_clip(h, 0, height-1);
+ if (start > end)
+ FFSWAP(int16_t, start, end);
+ for (k = start; k < end; k++) {
+ buf[k * linesize + 0] = color[0];
+ buf[k * linesize + 1] = color[1];
+ buf[k * linesize + 2] = color[2];
+ buf[k * linesize + 3] = color[3];
+ }
+}
+
+static void draw_sample_p2p_rgba_scale(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
{
int k;
if (h >= 0 && h < height) {
@@ -257,9 +296,35 @@ static void draw_sample_p2p_rgba(uint8_t *buf, int height, int linesize,
*prev_y = h;
}
-static void draw_sample_cline_rgba(uint8_t *buf, int height, int linesize,
- int16_t *prev_y,
- const uint8_t color[4], int h)
+static void draw_sample_p2p_rgba_full(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
+{
+ int k;
+ if (h >= 0 && h < height) {
+ buf[h * linesize + 0] = color[0];
+ buf[h * linesize + 1] = color[1];
+ buf[h * linesize + 2] = color[2];
+ buf[h * linesize + 3] = color[3];
+ if (*prev_y && h != *prev_y) {
+ int start = *prev_y;
+ int end = av_clip(h, 0, height-1);
+ if (start > end)
+ FFSWAP(int16_t, start, end);
+ for (k = start + 1; k < end; k++) {
+ buf[k * linesize + 0] = color[0];
+ buf[k * linesize + 1] = color[1];
+ buf[k * linesize + 2] = color[2];
+ buf[k * linesize + 3] = color[3];
+ }
+ }
+ }
+ *prev_y = h;
+}
+
+static void draw_sample_cline_rgba_scale(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
{
int k;
const int start = (height - h) / 2;
@@ -271,6 +336,20 @@ static void draw_sample_cline_rgba(uint8_t *buf, int height, int linesize,
buf[k * linesize + 3] += color[3];
}
}
+ static void draw_sample_cline_rgba_full(uint8_t *buf, int height, int linesize,
+ int16_t *prev_y,
+ const uint8_t color[4], int h)
+{
+ int k;
+ const int start = (height - h) / 2;
+ const int end = start + h;
+ for (k = start; k < end; k++) {
+ buf[k * linesize + 0] = color[0];
+ buf[k * linesize + 1] = color[1];
+ buf[k * linesize + 2] = color[2];
+ buf[k * linesize + 3] = color[3];
+ }
+}
static void draw_sample_point_gray(uint8_t *buf, int height, int linesize,
int16_t *prev_y,
@@ -368,10 +447,10 @@ static int config_output(AVFilterLink *outlink)
break;
case AV_PIX_FMT_RGBA:
switch (showwaves->mode) {
- case MODE_POINT: showwaves->draw_sample = draw_sample_point_rgba; break;
- case MODE_LINE: showwaves->draw_sample = draw_sample_line_rgba; break;
- case MODE_P2P: showwaves->draw_sample = draw_sample_p2p_rgba; break;
- case MODE_CENTERED_LINE: showwaves->draw_sample = draw_sample_cline_rgba; break;
+ case MODE_POINT: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_point_rgba_scale : draw_sample_point_rgba_full; break;
+ case MODE_LINE: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_line_rgba_scale : draw_sample_line_rgba_full; break;
+ case MODE_P2P: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_p2p_rgba_scale : draw_sample_p2p_rgba_full; break;
+ case MODE_CENTERED_LINE: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_cline_rgba_scale : draw_sample_cline_rgba_full; break;
default:
return AVERROR_BUG;
}
@@ -430,8 +509,12 @@ static int config_output(AVFilterLink *outlink)
if (!colors)
return AVERROR(ENOMEM);
- /* multiplication factor, pre-computed to avoid in-loop divisions */
- x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n);
+ if (showwaves->draw_mode == DRAW_SCALE) {
+ /* multiplication factor, pre-computed to avoid in-loop divisions */
+ x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n);
+ } else {
+ x = 255;
+ }
if (outlink->format == AV_PIX_FMT_RGBA) {
uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };