To be useful for adaptive thresholding with threshold filter.
Showing the changes to libavfilter (1 of 2 files). Show all
Unified · Split
| @@ -32,6 +32,7 @@ typedef struct MaskedThresholdContext { · 31 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | int threshold; |
| 34 | 34 | int planes; |
| 35 | + int mode; | |
| 35 | 36 | |
| 36 | 37 | int linesize[4]; |
| 37 | 38 | int planewidth[4], planeheight[4]; |
| @@ -43,15 +44,19 @@ typedef struct MaskedThresholdContext { · 5 unmodified lines | ||
| 43 | 44 | } MaskedThresholdContext; |
| 44 | 45 | |
| 45 | 46 | #define OFFSET(x) offsetof(MaskedThresholdContext, x) |
| 46 | −#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | |
| 47 | +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | |
| 48 | +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM | |
| 47 | 49 | |
| 48 | 50 | typedef struct ThreadData { |
| 49 | 51 | AVFrame *src, *ref, *dst; |
| 50 | 52 | } ThreadData; |
| 51 | 53 | |
| 52 | 54 | static const AVOption maskedthreshold_options[] = { |
| 53 | − { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, FLAGS }, | |
| 54 | − { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, | |
| 55 | + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, TFLAGS }, | |
| 56 | + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, TFLAGS }, | |
| 57 | + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, | |
| 58 | + { "abs", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, | |
| 59 | + { "diff", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, | |
| 55 | 60 | { NULL } |
| 56 | 61 | }; |
| 57 | 62 | |
| @@ -77,13 +82,29 @@ static const enum AVPixelFormat pix_fmts[] = { · 19 unmodified lines | ||
| 77 | 82 | AV_PIX_FMT_NONE |
| 78 | 83 | }; |
| 79 | 84 | |
| 80 | −static void threshold8(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w) | |
| 85 | +static void threshold8_diff(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w) | |
| 86 | +{ | |
| 87 | + for (int x = 0; x < w; x++) | |
| 88 | + dst[x] = (ref[x] - src[x] <= threshold) ? FFMAX(ref[x] - threshold, 0): src[x]; | |
| 89 | +} | |
| 90 | + | |
| 91 | +static void threshold8_abs(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w) | |
| 81 | 92 | { |
| 82 | 93 | for (int x = 0; x < w; x++) |
| 83 | 94 | dst[x] = FFABS(src[x] - ref[x]) <= threshold ? src[x] : ref[x]; |
| 84 | 95 | } |
| 85 | 96 | |
| 86 | −static void threshold16(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w) | |
| 97 | +static void threshold16_diff(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w) | |
| 98 | +{ | |
| 99 | + const uint16_t *src = (const uint16_t *)ssrc; | |
| 100 | + const uint16_t *ref = (const uint16_t *)rref; | |
| 101 | + uint16_t *dst = (uint16_t *)ddst; | |
| 102 | + | |
| 103 | + for (int x = 0; x < w; x++) | |
| 104 | + dst[x] = (ref[x] - src[x] <= threshold) ? FFMAX(ref[x] - threshold, 0): src[x]; | |
| 105 | +} | |
| 106 | + | |
| 107 | +static void threshold16_abs(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w) | |
| 87 | 108 | { |
| 88 | 109 | const uint16_t *src = (const uint16_t *)ssrc; |
| 89 | 110 | const uint16_t *ref = (const uint16_t *)rref; |
| @@ -115,9 +136,9 @@ static int config_input(AVFilterLink *inlink) · 25 unmodified lines | ||
| 115 | 136 | s->depth = desc->comp[0].depth; |
| 116 | 137 | |
| 117 | 138 | if (desc->comp[0].depth == 8) |
| 118 | − s->maskedthreshold = threshold8; | |
| 139 | + s->maskedthreshold = s->mode ? threshold8_diff : threshold8_abs; | |
| 119 | 140 | else |
| 120 | − s->maskedthreshold = threshold16; | |
| 141 | + s->maskedthreshold = s->mode ? threshold16_diff : threshold16_abs; | |
| 121 | 142 | |
| 122 | 143 | return 0; |
| 123 | 144 | } |