#include "video.h"
#include "libavutil/common.h"
#include "libavutil/mem.h"
+#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#define MIN_SIZE 3
uint32_t *sc[(MAX_SIZE * MAX_SIZE) - 1]; ///< finite state machine storage
} FilterParam;
-typedef struct {
+typedef struct UnsharpContext {
+ const AVClass *class;
+ int lmsize_x, lmsize_y, cmsize_x, cmsize_y;
+ float lamount, camount;
FilterParam luma; ///< luma parameters (width, height, amount)
FilterParam chroma; ///< chroma parameters (width, height, amount)
int hsub, vsub;
}
}
-static void set_filter_param(FilterParam *fp, int msize_x, int msize_y, double amount)
+static void set_filter_param(FilterParam *fp, int msize_x, int msize_y, float amount)
{
fp->msize_x = msize_x;
fp->msize_y = msize_y;
fp->halfscale = 1 << (fp->scalebits - 1);
}
-static av_cold int init(AVFilterContext *ctx, const char *args)
+static av_cold int init(AVFilterContext *ctx)
{
UnsharpContext *unsharp = ctx->priv;
- int lmsize_x = 5, cmsize_x = 5;
- int lmsize_y = 5, cmsize_y = 5;
- double lamount = 1.0f, camount = 0.0f;
-
- if (args)
- sscanf(args, "%d:%d:%lf:%d:%d:%lf", &lmsize_x, &lmsize_y, &lamount,
- &cmsize_x, &cmsize_y, &camount);
-
- if ((lamount && (lmsize_x < 2 || lmsize_y < 2)) ||
- (camount && (cmsize_x < 2 || cmsize_y < 2))) {
- av_log(ctx, AV_LOG_ERROR,
- "Invalid value <2 for lmsize_x:%d or lmsize_y:%d or cmsize_x:%d or cmsize_y:%d\n",
- lmsize_x, lmsize_y, cmsize_x, cmsize_y);
- return AVERROR(EINVAL);
- }
- set_filter_param(&unsharp->luma, lmsize_x, lmsize_y, lamount);
- set_filter_param(&unsharp->chroma, cmsize_x, cmsize_y, camount);
+ set_filter_param(&unsharp->luma, unsharp->lmsize_x, unsharp->lmsize_y, unsharp->lamount);
+ set_filter_param(&unsharp->chroma, unsharp->cmsize_x, unsharp->cmsize_y, unsharp->camount);
return 0;
}
static int config_props(AVFilterLink *link)
{
UnsharpContext *unsharp = link->dst->priv;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
- unsharp->hsub = av_pix_fmt_descriptors[link->format].log2_chroma_w;
- unsharp->vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
+ unsharp->hsub = desc->log2_chroma_w;
+ unsharp->vsub = desc->log2_chroma_h;
init_filter_param(link->dst, &unsharp->luma, "luma", link->w);
init_filter_param(link->dst, &unsharp->chroma, "chroma", SHIFTUP(link->w, unsharp->hsub));
free_filter_param(&unsharp->chroma);
}
-static int end_frame(AVFilterLink *link)
+static int filter_frame(AVFilterLink *link, AVFrame *in)
{
UnsharpContext *unsharp = link->dst->priv;
- AVFilterBufferRef *in = link->cur_buf;
- AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
+ AVFilterLink *outlink = link->dst->outputs[0];
+ AVFrame *out;
int cw = SHIFTUP(link->w, unsharp->hsub);
int ch = SHIFTUP(link->h, unsharp->vsub);
- int ret;
+
+ out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+ if (!out) {
+ av_frame_free(&in);
+ return AVERROR(ENOMEM);
+ }
+ av_frame_copy_props(out, in);
apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma);
apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma);
apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma);
- if ((ret = ff_draw_slice(link->dst->outputs[0], 0, link->h, 1)) < 0 ||
- (ret = ff_end_frame(link->dst->outputs[0])) < 0)
- return ret;
- return 0;
+ av_frame_free(&in);
+ return ff_filter_frame(outlink, out);
}
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
+#define OFFSET(x) offsetof(UnsharpContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
+static const AVOption options[] = {
+ { "luma_msize_x", "luma matrix horizontal size", OFFSET(lmsize_x), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS },
+ { "luma_msize_y", "luma matrix vertical size", OFFSET(lmsize_y), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS },
+ { "luma_amount", "luma effect strength", OFFSET(lamount), AV_OPT_TYPE_FLOAT, { .dbl = 1 }, -2, 5, FLAGS },
+ { "chroma_msize_x", "chroma matrix horizontal size", OFFSET(cmsize_x), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS },
+ { "chroma_msize_y", "chroma matrix vertical size", OFFSET(cmsize_y), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS },
+ { "chroma_amount", "chroma effect strength", OFFSET(camount), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, -2, 5, FLAGS },
+ { NULL },
+};
-AVFilter avfilter_vf_unsharp = {
+static const AVClass unsharp_class = {
+ .class_name = "unsharp",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVFilterPad avfilter_vf_unsharp_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .filter_frame = filter_frame,
+ .config_props = config_props,
+ },
+ { NULL }
+};
+
+static const AVFilterPad avfilter_vf_unsharp_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ },
+ { NULL }
+};
+
+AVFilter ff_vf_unsharp = {
.name = "unsharp",
.description = NULL_IF_CONFIG_SMALL("Sharpen or blur the input video."),
.priv_size = sizeof(UnsharpContext),
+ .priv_class = &unsharp_class,
.init = init,
.uninit = uninit,
.query_formats = query_formats,
- .inputs = (const AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
- .config_props = config_props,
- .min_perms = AV_PERM_READ, },
- { .name = NULL}},
-
- .outputs = (const AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO, },
- { .name = NULL}},
+ .inputs = avfilter_vf_unsharp_inputs,
+
+ .outputs = avfilter_vf_unsharp_outputs,
};