mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-24 08:12:44 +00:00
avfilter/avf_showwaves: add draw mode which controls how single sample is drawn
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
fe0fdc51b5
commit
a8c2d375ca
@ -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
|
||||
|
@ -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 };
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user