avfilter/vf_maskedthreshold: implement diff mode

To be useful for adaptive thresholding with threshold filter.
This commit is contained in:
Paul B Mahol 2022-10-21 20:08:24 +02:00
parent a1a87b7a24
commit da4ff1d536
2 changed files with 32 additions and 7 deletions

View File

@ -16623,6 +16623,10 @@ video streams.
Set which planes will be processed as bitmap, unprocessed planes will be Set which planes will be processed as bitmap, unprocessed planes will be
copied from second stream. copied from second stream.
By default value 0xf, all planes will be processed. By default value 0xf, all planes will be processed.
@item mode
Set mode of filter operation. Can be @code{abs} or @code{diff}.
Default is @code{abs}.
@end table @end table
@subsection Commands @subsection Commands

View File

@ -32,6 +32,7 @@ typedef struct MaskedThresholdContext {
int threshold; int threshold;
int planes; int planes;
int mode;
int linesize[4]; int linesize[4];
int planewidth[4], planeheight[4]; int planewidth[4], planeheight[4];
@ -43,15 +44,19 @@ typedef struct MaskedThresholdContext {
} MaskedThresholdContext; } MaskedThresholdContext;
#define OFFSET(x) offsetof(MaskedThresholdContext, x) #define OFFSET(x) offsetof(MaskedThresholdContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
typedef struct ThreadData { typedef struct ThreadData {
AVFrame *src, *ref, *dst; AVFrame *src, *ref, *dst;
} ThreadData; } ThreadData;
static const AVOption maskedthreshold_options[] = { static const AVOption maskedthreshold_options[] = {
{ "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, FLAGS }, { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, TFLAGS },
{ "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, TFLAGS },
{ "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" },
{ "abs", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
{ "diff", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
{ NULL } { NULL }
}; };
@ -77,13 +82,29 @@ static const enum AVPixelFormat pix_fmts[] = {
AV_PIX_FMT_NONE AV_PIX_FMT_NONE
}; };
static void threshold8(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w) static void threshold8_diff(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w)
{
for (int x = 0; x < w; x++)
dst[x] = (ref[x] - src[x] <= threshold) ? FFMAX(ref[x] - threshold, 0): src[x];
}
static void threshold8_abs(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w)
{ {
for (int x = 0; x < w; x++) for (int x = 0; x < w; x++)
dst[x] = FFABS(src[x] - ref[x]) <= threshold ? src[x] : ref[x]; dst[x] = FFABS(src[x] - ref[x]) <= threshold ? src[x] : ref[x];
} }
static void threshold16(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w) static void threshold16_diff(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w)
{
const uint16_t *src = (const uint16_t *)ssrc;
const uint16_t *ref = (const uint16_t *)rref;
uint16_t *dst = (uint16_t *)ddst;
for (int x = 0; x < w; x++)
dst[x] = (ref[x] - src[x] <= threshold) ? FFMAX(ref[x] - threshold, 0): src[x];
}
static void threshold16_abs(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w)
{ {
const uint16_t *src = (const uint16_t *)ssrc; const uint16_t *src = (const uint16_t *)ssrc;
const uint16_t *ref = (const uint16_t *)rref; const uint16_t *ref = (const uint16_t *)rref;
@ -115,9 +136,9 @@ static int config_input(AVFilterLink *inlink)
s->depth = desc->comp[0].depth; s->depth = desc->comp[0].depth;
if (desc->comp[0].depth == 8) if (desc->comp[0].depth == 8)
s->maskedthreshold = threshold8; s->maskedthreshold = s->mode ? threshold8_diff : threshold8_abs;
else else
s->maskedthreshold = threshold16; s->maskedthreshold = s->mode ? threshold16_diff : threshold16_abs;
return 0; return 0;
} }