Commit d7ae4f79 authored by Paul B Mahol's avatar Paul B Mahol

avfilter/f_drawgraph: add another slide mode

parent 37abc8cc
...@@ -6438,6 +6438,9 @@ Scroll from right to left. ...@@ -6438,6 +6438,9 @@ Scroll from right to left.
@item rscroll @item rscroll
Scroll from left to right. Scroll from left to right.
@item picture
Draw single picture.
@end table @end table
Default is @code{frame}. Default is @code{frame}.
......
...@@ -44,6 +44,9 @@ typedef struct DrawGraphContext { ...@@ -44,6 +44,9 @@ typedef struct DrawGraphContext {
int x; int x;
int prev_y[4]; int prev_y[4];
int first; int first;
float *values[4];
int values_size[4];
int nb_values;
} DrawGraphContext; } DrawGraphContext;
#define OFFSET(x) offsetof(DrawGraphContext, x) #define OFFSET(x) offsetof(DrawGraphContext, x)
...@@ -65,11 +68,12 @@ static const AVOption drawgraph_options[] = { ...@@ -65,11 +68,12 @@ static const AVOption drawgraph_options[] = {
{"bar", "draw bars", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode"}, {"bar", "draw bars", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode"},
{"dot", "draw dots", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode"}, {"dot", "draw dots", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode"},
{"line", "draw lines", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mode"}, {"line", "draw lines", OFFSET(mode), AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mode"},
{ "slide", "set slide mode", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "slide" }, { "slide", "set slide mode", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=0}, 0, 4, FLAGS, "slide" },
{"frame", "draw new frames", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "slide"}, {"frame", "draw new frames", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "slide"},
{"replace", "replace old columns with new", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "slide"}, {"replace", "replace old columns with new", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "slide"},
{"scroll", "scroll from right to left", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "slide"}, {"scroll", "scroll from right to left", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "slide"},
{"rscroll", "scroll from left to right", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "slide"}, {"rscroll", "scroll from left to right", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "slide"},
{"picture", "display graph in single frame", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "slide"},
{ "size", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS }, { "size", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS },
{ "s", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS }, { "s", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS },
{ NULL } { NULL }
...@@ -100,6 +104,18 @@ static av_cold int init(AVFilterContext *ctx) ...@@ -100,6 +104,18 @@ static av_cold int init(AVFilterContext *ctx)
s->first = 1; s->first = 1;
if (s->slide == 4) {
s->values[0] = av_fast_realloc(NULL, &s->values_size[0], 2000);
s->values[1] = av_fast_realloc(NULL, &s->values_size[1], 2000);
s->values[2] = av_fast_realloc(NULL, &s->values_size[2], 2000);
s->values[3] = av_fast_realloc(NULL, &s->values_size[3], 2000);
if (!s->values[0] || !s->values[1] ||
!s->values[2] || !s->values[3]) {
return AVERROR(ENOMEM);
}
}
return 0; return 0;
} }
...@@ -144,19 +160,45 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -144,19 +160,45 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
AVFrame *out = s->out; AVFrame *out = s->out;
int i; int i;
if (!s->out || s->out->width != outlink->w || if (s->slide == 4 && s->nb_values >= s->values_size[0] / sizeof(float)) {
s->out->height != outlink->h) { float *ptr;
av_frame_free(&s->out);
s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h); ptr = av_fast_realloc(s->values[0], &s->values_size[0], s->values_size[0] * 2);
out = s->out; if (!ptr)
if (!s->out) {
av_frame_free(&in);
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} s->values[0] = ptr;
ptr = av_fast_realloc(s->values[1], &s->values_size[1], s->values_size[1] * 2);
if (!ptr)
return AVERROR(ENOMEM);
s->values[1] = ptr;
ptr = av_fast_realloc(s->values[2], &s->values_size[2], s->values_size[2] * 2);
if (!ptr)
return AVERROR(ENOMEM);
s->values[2] = ptr;
clear_image(s, out, outlink); ptr = av_fast_realloc(s->values[3], &s->values_size[3], s->values_size[3] * 2);
if (!ptr)
return AVERROR(ENOMEM);
s->values[3] = ptr;
}
if (s->slide != 4 || s->nb_values == 0) {
if (!s->out || s->out->width != outlink->w ||
s->out->height != outlink->h) {
av_frame_free(&s->out);
s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
out = s->out;
if (!s->out) {
av_frame_free(&in);
return AVERROR(ENOMEM);
}
clear_image(s, out, outlink);
}
av_frame_copy_props(out, in);
} }
av_frame_copy_props(out, in);
metadata = av_frame_get_metadata(in); metadata = av_frame_get_metadata(in);
...@@ -166,6 +208,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -166,6 +208,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
uint32_t fg, bg; uint32_t fg, bg;
float vf; float vf;
if (s->slide == 4)
s->values[i][s->nb_values] = NAN;
e = av_dict_get(metadata, s->key[i], NULL, 0); e = av_dict_get(metadata, s->key[i], NULL, 0);
if (!e || !e->value) if (!e || !e->value)
continue; continue;
...@@ -175,6 +220,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -175,6 +220,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
vf = av_clipf(vf, s->min, s->max); vf = av_clipf(vf, s->min, s->max);
if (s->slide == 4) {
s->values[i][s->nb_values] = vf;
continue;
}
values[VAR_MIN] = s->min; values[VAR_MIN] = s->min;
values[VAR_MAX] = s->max; values[VAR_MAX] = s->max;
values[VAR_VAL] = vf; values[VAR_VAL] = vf;
...@@ -255,12 +305,99 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -255,12 +305,99 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
} }
} }
s->nb_values++;
s->x++; s->x++;
av_frame_free(&in); av_frame_free(&in);
if (s->slide == 4)
return 0;
return ff_filter_frame(outlink, av_frame_clone(s->out)); return ff_filter_frame(outlink, av_frame_clone(s->out));
} }
static int request_frame(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
DrawGraphContext *s = ctx->priv;
AVFrame *out = s->out;
int ret, i, k, step, l;
ret = ff_request_frame(ctx->inputs[0]);
if (s->slide == 4 && ret == AVERROR_EOF && s->nb_values > 0) {
s->x = l = 0;
step = ceil(s->nb_values / (float)s->w);
for (k = 0; k < s->nb_values; k++) {
for (i = 0; i < 4; i++) {
double values[VAR_VARS_NB];
int j, y, x, old;
uint32_t fg, bg;
float vf = s->values[i][k];
if (isnan(vf))
continue;
values[VAR_MIN] = s->min;
values[VAR_MAX] = s->max;
values[VAR_VAL] = vf;
fg = av_expr_eval(s->fg_expr[i], values, NULL);
bg = AV_RN32(s->bg);
x = s->x;
y = (outlink->h - 1) * (1 - ((vf - s->min) / (s->max - s->min)));
switch (s->mode) {
case 0:
old = AV_RN32(out->data[0] + y * out->linesize[0] + x * 4);
for (j = y; j < outlink->h; j++) {
if (old != bg &&
(AV_RN32(out->data[0] + j * out->linesize[0] + x * 4) != old) ||
AV_RN32(out->data[0] + FFMIN(j+1, outlink->h - 1) * out->linesize[0] + x * 4) != old) {
draw_dot(fg, x, j, out);
break;
}
draw_dot(fg, x, j, out);
}
break;
case 1:
draw_dot(fg, x, y, out);
break;
case 2:
if (s->first) {
s->first = 0;
s->prev_y[i] = y;
}
if (y <= s->prev_y[i]) {
for (j = y; j <= s->prev_y[i]; j++)
draw_dot(fg, x, j, out);
} else {
for (j = s->prev_y[i]; j <= y; j++)
draw_dot(fg, x, j, out);
}
s->prev_y[i] = y;
break;
}
}
l++;
if (l >= step) {
l = 0;
s->x++;
}
}
s->nb_values = 0;
out->pts = 0;
ret = ff_filter_frame(ctx->outputs[0], s->out);
}
return ret;
}
static int config_output(AVFilterLink *outlink) static int config_output(AVFilterLink *outlink)
{ {
DrawGraphContext *s = outlink->src->priv; DrawGraphContext *s = outlink->src->priv;
...@@ -279,7 +416,14 @@ static av_cold void uninit(AVFilterContext *ctx) ...@@ -279,7 +416,14 @@ static av_cold void uninit(AVFilterContext *ctx)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
av_expr_free(s->fg_expr[i]); av_expr_free(s->fg_expr[i]);
av_frame_free(&s->out);
if (s->slide != 4)
av_frame_free(&s->out);
av_freep(&s->values[0]);
av_freep(&s->values[1]);
av_freep(&s->values[2]);
av_freep(&s->values[3]);
} }
#if CONFIG_DRAWGRAPH_FILTER #if CONFIG_DRAWGRAPH_FILTER
...@@ -300,6 +444,7 @@ static const AVFilterPad drawgraph_outputs[] = { ...@@ -300,6 +444,7 @@ static const AVFilterPad drawgraph_outputs[] = {
.name = "default", .name = "default",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
.config_props = config_output, .config_props = config_output,
.request_frame = request_frame,
}, },
{ NULL } { NULL }
}; };
...@@ -337,6 +482,7 @@ static const AVFilterPad adrawgraph_outputs[] = { ...@@ -337,6 +482,7 @@ static const AVFilterPad adrawgraph_outputs[] = {
.name = "default", .name = "default",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
.config_props = config_output, .config_props = config_output,
.request_frame = request_frame,
}, },
{ NULL } { NULL }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment