if (!args) {
av_log(ctx, AV_LOG_ERROR,
- "Filter expects 2 or 4 arguments, none provided\n");
+ "Filter expects 2 or 4 or 6 arguments, none provided\n");
return AVERROR(EINVAL);
}
char *expr;
int ret;
- if (!(boxblur->temp[0] = av_malloc(w)) ||
- !(boxblur->temp[1] = av_malloc(w)))
+ if (!(boxblur->temp[0] = av_malloc(FFMAX(w, h))) ||
+ !(boxblur->temp[1] = av_malloc(FFMAX(w, h))))
return AVERROR(ENOMEM);
boxblur->hsub = desc->log2_chroma_w;
}
static inline void blur(uint8_t *dst, int dst_step, const uint8_t *src, int src_step,
- int w, int radius)
+ int len, int radius)
{
/* Naive boxblur would sum source pixels from x-radius .. x+radius
* for destination pixel x. That would be O(radius*width).
dst[x*dst_step] = (sum*inv + (1<<15))>>16;
}
- for (; x < w-radius; x++) {
+ for (; x < len-radius; x++) {
sum += src[(radius+x)*src_step] - src[(x-radius-1)*src_step];
dst[x*dst_step] = (sum*inv + (1<<15))>>16;
}
- for (; x < w; x++) {
- sum += src[(2*w-radius-x-1)*src_step] - src[(x-radius-1)*src_step];
+ for (; x < len; x++) {
+ sum += src[(2*len-radius-x-1)*src_step] - src[(x-radius-1)*src_step];
dst[x*dst_step] = (sum*inv + (1<<15))>>16;
}
}
static inline void blur_power(uint8_t *dst, int dst_step, const uint8_t *src, int src_step,
- int w, int radius, int power, uint8_t *temp[2])
+ int len, int radius, int power, uint8_t *temp[2])
{
uint8_t *a = temp[0], *b = temp[1];
if (radius && power) {
- blur(a, 1, src, src_step, w, radius);
+ blur(a, 1, src, src_step, len, radius);
for (; power > 2; power--) {
uint8_t *c;
- blur(b, 1, a, 1, w, radius);
+ blur(b, 1, a, 1, len, radius);
c = a; a = b; b = c;
}
if (power > 1) {
- blur(dst, dst_step, a, 1, w, radius);
+ blur(dst, dst_step, a, 1, len, radius);
} else {
int i;
- for (i = 0; i < w; i++)
+ for (i = 0; i < len; i++)
dst[i*dst_step] = a[i];
}
} else {
int i;
- for (i = 0; i < w; i++)
+ for (i = 0; i < len; i++)
dst[i*dst_step] = src[i*src_step];
}
}
h, radius, power, temp);
}
-static void draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir)
+static void null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { }
+
+static void end_frame(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->dst;
BoxBlurContext *boxblur = ctx->priv;
AVFilterBufferRef *inpicref = inlink ->cur_buf;
AVFilterBufferRef *outpicref = outlink->out_buf;
int plane;
- int cw = inlink->w >> boxblur->hsub, ch = h0 >> boxblur->vsub;
+ int cw = inlink->w >> boxblur->hsub, ch = inlink->h >> boxblur->vsub;
int w[4] = { inlink->w, cw, cw, inlink->w };
- int h[4] = { h0, ch, ch, h0 };
- uint8_t *dst[4], *src[4];
-
- for (plane = 0; inpicref->data[plane] && plane < 4; plane++) {
- int y = plane == 1 || plane == 2 ? y0 >> boxblur->vsub : y0;
- src[plane] = inpicref ->data[plane] + inpicref ->linesize[plane] * y;
- dst[plane] = outpicref->data[plane] + outpicref->linesize[plane] * y;
- }
+ int h[4] = { inlink->h, ch, ch, inlink->h };
for (plane = 0; inpicref->data[plane] && plane < 4; plane++)
hblur(outpicref->data[plane], outpicref->linesize[plane],
outpicref->data[plane], outpicref->linesize[plane],
w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
boxblur->temp);
+
+ avfilter_draw_slice(outlink, 0, inlink->h, 1);
+ avfilter_end_frame(outlink);
}
AVFilter avfilter_vf_boxblur = {
.inputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
- .draw_slice = draw_slice,
+ .draw_slice = null_draw_slice,
+ .end_frame = end_frame,
.min_perms = AV_PERM_READ },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",