mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-24 03:59:43 +00:00
avfilter/vf_datascope: add option to show only subset of components
This commit is contained in:
parent
eb0f532c98
commit
8d86d58941
@ -9207,6 +9207,9 @@ Set background opacity.
|
|||||||
|
|
||||||
@item format
|
@item format
|
||||||
Set display number format. Can be @code{hex}, or @code{dec}. Default is @code{hex}.
|
Set display number format. Can be @code{hex}, or @code{dec}. Default is @code{hex}.
|
||||||
|
|
||||||
|
@item components
|
||||||
|
Set pixel components to display. By default all pixel components are displayed.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@section dblur
|
@section dblur
|
||||||
|
@ -37,6 +37,7 @@ typedef struct DatascopeContext {
|
|||||||
int mode;
|
int mode;
|
||||||
int dformat;
|
int dformat;
|
||||||
int axis;
|
int axis;
|
||||||
|
int components;
|
||||||
float opacity;
|
float opacity;
|
||||||
|
|
||||||
int nb_planes;
|
int nb_planes;
|
||||||
@ -71,6 +72,7 @@ static const AVOption datascope_options[] = {
|
|||||||
{ "format", "set display number format", OFFSET(dformat), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "format" },
|
{ "format", "set display number format", OFFSET(dformat), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "format" },
|
||||||
{ "hex", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "format" },
|
{ "hex", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "format" },
|
||||||
{ "dec", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "format" },
|
{ "dec", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "format" },
|
||||||
|
{ "components", "set components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=15}, 1, 15, FLAGS },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,7 +171,7 @@ static void reverse_color16(FFDrawContext *draw, FFDrawColor *color, FFDrawColor
|
|||||||
|
|
||||||
typedef struct ThreadData {
|
typedef struct ThreadData {
|
||||||
AVFrame *in, *out;
|
AVFrame *in, *out;
|
||||||
int xoff, yoff;
|
int xoff, yoff, PP;
|
||||||
} ThreadData;
|
} ThreadData;
|
||||||
|
|
||||||
static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
@ -180,13 +182,14 @@ static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
|
|||||||
ThreadData *td = arg;
|
ThreadData *td = arg;
|
||||||
AVFrame *in = td->in;
|
AVFrame *in = td->in;
|
||||||
AVFrame *out = td->out;
|
AVFrame *out = td->out;
|
||||||
|
const int PP = td->PP;
|
||||||
const int xoff = td->xoff;
|
const int xoff = td->xoff;
|
||||||
const int yoff = td->yoff;
|
const int yoff = td->yoff;
|
||||||
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
||||||
const int C = s->chars;
|
const int C = s->chars;
|
||||||
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
||||||
const int W = (outlink->w - xoff) / (C * 10);
|
const int W = (outlink->w - xoff) / (C * 10);
|
||||||
const int H = (outlink->h - yoff) / (P * 12);
|
const int H = (outlink->h - yoff) / (PP * 12);
|
||||||
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
||||||
const int slice_start = (W * jobnr) / nb_jobs;
|
const int slice_start = (W * jobnr) / nb_jobs;
|
||||||
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
||||||
@ -196,18 +199,21 @@ static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
|
|||||||
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
||||||
FFDrawColor color = { { 0 } };
|
FFDrawColor color = { { 0 } };
|
||||||
FFDrawColor reverse = { { 0 } };
|
FFDrawColor reverse = { { 0 } };
|
||||||
int value[4] = { 0 };
|
int value[4] = { 0 }, pp = 0;
|
||||||
|
|
||||||
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
||||||
s->reverse_color(&s->draw, &color, &reverse);
|
s->reverse_color(&s->draw, &color, &reverse);
|
||||||
ff_fill_rectangle(&s->draw, &color, out->data, out->linesize,
|
ff_fill_rectangle(&s->draw, &color, out->data, out->linesize,
|
||||||
xoff + x * C * 10, yoff + y * P * 12, C * 10, P * 12);
|
xoff + x * C * 10, yoff + y * PP * 12, C * 10, PP * 12);
|
||||||
|
|
||||||
for (p = 0; p < P; p++) {
|
for (p = 0; p < P; p++) {
|
||||||
char text[256];
|
char text[256];
|
||||||
|
|
||||||
|
if (!(s->components & (1 << p)))
|
||||||
|
continue;
|
||||||
snprintf(text, sizeof(text), format[D], value[p]);
|
snprintf(text, sizeof(text), format[D], value[p]);
|
||||||
draw_text(&s->draw, out, &reverse, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
|
draw_text(&s->draw, out, &reverse, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
|
||||||
|
pp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,13 +229,14 @@ static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
|||||||
ThreadData *td = arg;
|
ThreadData *td = arg;
|
||||||
AVFrame *in = td->in;
|
AVFrame *in = td->in;
|
||||||
AVFrame *out = td->out;
|
AVFrame *out = td->out;
|
||||||
|
const int PP = td->PP;
|
||||||
const int xoff = td->xoff;
|
const int xoff = td->xoff;
|
||||||
const int yoff = td->yoff;
|
const int yoff = td->yoff;
|
||||||
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
||||||
const int C = s->chars;
|
const int C = s->chars;
|
||||||
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
||||||
const int W = (outlink->w - xoff) / (C * 10);
|
const int W = (outlink->w - xoff) / (C * 10);
|
||||||
const int H = (outlink->h - yoff) / (P * 12);
|
const int H = (outlink->h - yoff) / (PP * 12);
|
||||||
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
||||||
const int slice_start = (W * jobnr) / nb_jobs;
|
const int slice_start = (W * jobnr) / nb_jobs;
|
||||||
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
||||||
@ -238,15 +245,18 @@ static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
|||||||
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
|
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
|
||||||
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
||||||
FFDrawColor color = { { 0 } };
|
FFDrawColor color = { { 0 } };
|
||||||
int value[4] = { 0 };
|
int value[4] = { 0 }, pp = 0;
|
||||||
|
|
||||||
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
||||||
|
|
||||||
for (p = 0; p < P; p++) {
|
for (p = 0; p < P; p++) {
|
||||||
char text[256];
|
char text[256];
|
||||||
|
|
||||||
|
if (!(s->components & (1 << p)))
|
||||||
|
continue;
|
||||||
snprintf(text, sizeof(text), format[D], value[p]);
|
snprintf(text, sizeof(text), format[D], value[p]);
|
||||||
draw_text(&s->draw, out, &color, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
|
draw_text(&s->draw, out, &color, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
|
||||||
|
pp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,13 +272,14 @@ static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
|||||||
ThreadData *td = arg;
|
ThreadData *td = arg;
|
||||||
AVFrame *in = td->in;
|
AVFrame *in = td->in;
|
||||||
AVFrame *out = td->out;
|
AVFrame *out = td->out;
|
||||||
|
const int PP = td->PP;
|
||||||
const int xoff = td->xoff;
|
const int xoff = td->xoff;
|
||||||
const int yoff = td->yoff;
|
const int yoff = td->yoff;
|
||||||
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
||||||
const int C = s->chars;
|
const int C = s->chars;
|
||||||
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
|
||||||
const int W = (outlink->w - xoff) / (C * 10);
|
const int W = (outlink->w - xoff) / (C * 10);
|
||||||
const int H = (outlink->h - yoff) / (P * 12);
|
const int H = (outlink->h - yoff) / (PP * 12);
|
||||||
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
|
||||||
const int slice_start = (W * jobnr) / nb_jobs;
|
const int slice_start = (W * jobnr) / nb_jobs;
|
||||||
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
const int slice_end = (W * (jobnr+1)) / nb_jobs;
|
||||||
@ -277,14 +288,17 @@ static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
|||||||
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
|
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
|
||||||
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
|
||||||
FFDrawColor color = { { 0 } };
|
FFDrawColor color = { { 0 } };
|
||||||
int value[4] = { 0 };
|
int value[4] = { 0 }, pp = 0;
|
||||||
|
|
||||||
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
|
||||||
for (p = 0; p < P; p++) {
|
for (p = 0; p < P; p++) {
|
||||||
char text[256];
|
char text[256];
|
||||||
|
|
||||||
|
if (!(s->components & (1 << p)))
|
||||||
|
continue;
|
||||||
snprintf(text, sizeof(text), format[D], value[p]);
|
snprintf(text, sizeof(text), format[D], value[p]);
|
||||||
draw_text(&s->draw, out, &s->white, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
|
draw_text(&s->draw, out, &s->white, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
|
||||||
|
pp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,9 +311,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
|
|||||||
AVFilterContext *ctx = inlink->dst;
|
AVFilterContext *ctx = inlink->dst;
|
||||||
DatascopeContext *s = ctx->priv;
|
DatascopeContext *s = ctx->priv;
|
||||||
AVFilterLink *outlink = ctx->outputs[0];
|
AVFilterLink *outlink = ctx->outputs[0];
|
||||||
|
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
||||||
ThreadData td = { 0 };
|
ThreadData td = { 0 };
|
||||||
int ymaxlen = 0;
|
int ymaxlen = 0;
|
||||||
int xmaxlen = 0;
|
int xmaxlen = 0;
|
||||||
|
int PP = 0;
|
||||||
AVFrame *out;
|
AVFrame *out;
|
||||||
|
|
||||||
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
|
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
|
||||||
@ -312,10 +328,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
|
|||||||
ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize,
|
ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize,
|
||||||
0, 0, outlink->w, outlink->h);
|
0, 0, outlink->w, outlink->h);
|
||||||
|
|
||||||
|
for (int p = 0; p < P; p++) {
|
||||||
|
if (s->components & (1 << p))
|
||||||
|
PP++;
|
||||||
|
}
|
||||||
|
PP = FFMAX(PP, 1);
|
||||||
|
|
||||||
if (s->axis) {
|
if (s->axis) {
|
||||||
const int P = FFMAX(s->nb_planes, s->nb_comps);
|
|
||||||
const int C = s->chars;
|
const int C = s->chars;
|
||||||
int Y = outlink->h / (P * 12);
|
int Y = outlink->h / (PP * 12);
|
||||||
int X = outlink->w / (C * 10);
|
int X = outlink->w / (C * 10);
|
||||||
char text[256] = { 0 };
|
char text[256] = { 0 };
|
||||||
int x, y;
|
int x, y;
|
||||||
@ -327,16 +348,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
|
|||||||
xmaxlen = strlen(text);
|
xmaxlen = strlen(text);
|
||||||
xmaxlen *= 10;
|
xmaxlen *= 10;
|
||||||
|
|
||||||
Y = (outlink->h - xmaxlen) / (P * 12);
|
Y = (outlink->h - xmaxlen) / (PP * 12);
|
||||||
X = (outlink->w - ymaxlen) / (C * 10);
|
X = (outlink->w - ymaxlen) / (C * 10);
|
||||||
|
|
||||||
for (y = 0; y < Y; y++) {
|
for (y = 0; y < Y; y++) {
|
||||||
snprintf(text, sizeof(text), "%d", s->y + y);
|
snprintf(text, sizeof(text), "%d", s->y + y);
|
||||||
|
|
||||||
ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
|
ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
|
||||||
0, xmaxlen + y * P * 12 + (P + 1) * P - 2, ymaxlen, 10);
|
0, xmaxlen + y * PP * 12 + (PP + 1) * PP - 2, ymaxlen, 10);
|
||||||
|
|
||||||
draw_text(&s->draw, out, &s->yellow, 2, xmaxlen + y * P * 12 + (P + 1) * P, text, 0);
|
draw_text(&s->draw, out, &s->yellow, 2, xmaxlen + y * PP * 12 + (PP + 1) * PP, text, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < X; x++) {
|
for (x = 0; x < X; x++) {
|
||||||
@ -349,7 +370,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen;
|
td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen, td.PP = PP;
|
||||||
ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(ff_filter_get_nb_threads(ctx), FFMAX(outlink->w / 20, 1)));
|
ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(ff_filter_get_nb_threads(ctx), FFMAX(outlink->w / 20, 1)));
|
||||||
|
|
||||||
av_frame_free(&in);
|
av_frame_free(&in);
|
||||||
|
Loading…
Reference in New Issue
Block a user