summaryrefslogtreecommitdiff
path: root/libavfilter/vf_xmedian.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2020-02-12 14:34:00 +0100
committerPaul B Mahol <onemda@gmail.com>2020-02-12 14:59:32 +0100
commit47773f7979d77c1fcd08b57e85af1ad08d9248c8 (patch)
tree94ef01cd73d9f761931c704c352e8ff3d778f6f6 /libavfilter/vf_xmedian.c
parent28743f1803721b6d0b7dcfcc1cb07c1e58f8cc12 (diff)
downloadffmpeg-47773f7979d77c1fcd08b57e85af1ad08d9248c8.tar.gz
avfilter/vf_xmedian: implement percentile option
Diffstat (limited to 'libavfilter/vf_xmedian.c')
-rw-r--r--libavfilter/vf_xmedian.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c
index 49ba8f44f1..52c5b060fa 100644
--- a/libavfilter/vf_xmedian.c
+++ b/libavfilter/vf_xmedian.c
@@ -36,8 +36,10 @@ typedef struct XMedianContext {
const AVPixFmtDescriptor *desc;
int nb_inputs;
int planes;
+ float percentile;
int radius;
+ int index;
int depth;
int max;
int nb_planes;
@@ -94,6 +96,10 @@ static av_cold int init(AVFilterContext *ctx)
int ret;
s->radius = s->nb_inputs / 2;
+ if (s->nb_inputs & 1)
+ s->index = s->radius * 2.f * s->percentile;
+ else
+ s->index = av_clip(s->radius * 2.f * s->percentile, 1, s->nb_inputs - 1);
s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames));
if (!s->frames)
return AVERROR(ENOMEM);
@@ -134,6 +140,7 @@ static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
AVFrame *out = td->out;
const int nb_inputs = s->nb_inputs;
const int radius = s->radius;
+ const int index = s->index;
int values[256];
for (int p = 0; p < s->nb_planes; p++) {
@@ -143,8 +150,8 @@ static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
if (!((1 << p) & s->planes)) {
av_image_copy_plane((uint8_t *)dst, out->linesize[p],
- in[0]->data[p] + slice_start * in[radius]->linesize[p],
- in[0]->linesize[p],
+ in[radius]->data[p] + slice_start * in[radius]->linesize[p],
+ in[radius]->linesize[p],
s->linesize[p], slice_end - slice_start);
continue;
}
@@ -157,10 +164,10 @@ static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
}
AV_QSORT(values, nb_inputs, int, comparei);
- if (radius & 1)
- dst[x] = values[radius];
+ if (nb_inputs & 1)
+ dst[x] = values[index];
else
- dst[x] = (values[radius] + values[radius - 1]) >> 1;
+ dst[x] = (values[index] + values[index - 1]) >> 1;
}
dst += out->linesize[p] / 2;
@@ -178,6 +185,7 @@ static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
AVFrame *out = td->out;
const int nb_inputs = s->nb_inputs;
const int radius = s->radius;
+ const int index = s->index;
int values[256];
for (int p = 0; p < s->nb_planes; p++) {
@@ -187,8 +195,8 @@ static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
if (!((1 << p) & s->planes)) {
av_image_copy_plane(dst, out->linesize[p],
- in[0]->data[p] + slice_start * in[0]->linesize[p],
- in[0]->linesize[p],
+ in[radius]->data[p] + slice_start * in[radius]->linesize[p],
+ in[radius]->linesize[p],
s->linesize[p], slice_end - slice_start);
continue;
}
@@ -199,10 +207,10 @@ static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
values[i] = in[i]->data[p][y * in[i]->linesize[p] + x];
AV_QSORT(values, nb_inputs, int, comparei);
- if (radius & 1)
- dst[x] = values[radius];
+ if (nb_inputs & 1)
+ dst[x] = values[index];
else
- dst[x] = (values[radius] + values[radius - 1]) >> 1;
+ dst[x] = (values[index] + values[index - 1]) >> 1;
}
dst += out->linesize[p];
@@ -328,6 +336,7 @@ static int activate(AVFilterContext *ctx)
static const AVOption xmedian_options[] = {
{ "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=3}, 3, 255, .flags = FLAGS },
{ "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, .flags = FLAGS },
+ { "percentile", "set percentile", OFFSET(percentile),AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, .flags = FLAGS },
{ NULL },
};