[PATCH] avfilter: port qp filter from libmpcodecs
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavfilter/vf_qp.c diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..e7cac2d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table +@section qp + +Quantization Parameter (QP) change filter. + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @option +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equatition like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..b5b122e --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int8_t *qp; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + av_reallocp_array(&s->qp, s->qstride * s->h, sizeof(*s->qp)); + if (!s->qp) + return AVERROR(ENOMEM); + + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + QPContext *s = ctx->priv; + AVFrame *out; + + if (!s->qp_expr_str || ctx->is_disabled) + return ff_filter_frame(outlink, in); + + out = av_frame_clone(in); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + + out->qscale_table = s->qp; + out->qstride = s->qstride; + + if (in->qscale_table) { + int y, x; + + for (y = 0; y < s->h; y++) + for (x = 0; x < out->qstride; x++) + out->qscale_table[x + out->qstride * y] = s->lut[129 + + ((int8_t)in->qscale_table[x + in->qstride * y])]; + } else { + int y, x, qp = s->lut[0]; + + for (y = 0; y < s->h; y++) + for (x = 0; x < out->qstride; x++) + out->qscale_table[x + out->qstride * y] = qp; + } + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + QPContext *s = ctx->priv; + + av_freep(&s->qp); +} + +static const AVFilterPad qp_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad qp_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter avfilter_vf_qp = { + .name = "qp", + .description = NULL_IF_CONFIG_SMALL("Change Quantization Parameter."), + .priv_size = sizeof(QPContext), + .uninit = uninit, + .inputs = qp_inputs, + .outputs = qp_outputs, + .priv_class = &qp_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, +}; -- 1.7.11.2
On Wed, Sep 18, 2013 at 06:34:36PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavfilter/vf_qp.c
[...]
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + QPContext *s = ctx->priv; + AVFrame *out; + + if (!s->qp_expr_str || ctx->is_disabled) + return ff_filter_frame(outlink, in); + + out = av_frame_clone(in); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } +
+ out->qscale_table = s->qp;
So the table is valid for an undefined amount of time? With the ref counting API, I believe this is not the desired behaviour. [...] -- Clément B.
On 9/18/13, Clement Boesch <u@pkh.me> wrote:
On Wed, Sep 18, 2013 at 06:34:36PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavfilter/vf_qp.c
[...]
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + QPContext *s = ctx->priv; + AVFrame *out; + + if (!s->qp_expr_str || ctx->is_disabled) + return ff_filter_frame(outlink, in); + + out = av_frame_clone(in); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } +
+ out->qscale_table = s->qp;
So the table is valid for an undefined amount of time? With the ref counting API, I believe this is not the desired behaviour.
Right, silly me. I will copy it. Is there something else?
[...]
-- Clement B.
On 9/18/13, Paul B Mahol <onemda@gmail.com> wrote:
On 9/18/13, Clement Boesch <u@pkh.me> wrote:
On Wed, Sep 18, 2013 at 06:34:36PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavfilter/vf_qp.c
[...]
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + QPContext *s = ctx->priv; + AVFrame *out; + + if (!s->qp_expr_str || ctx->is_disabled) + return ff_filter_frame(outlink, in); + + out = av_frame_clone(in); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } +
+ out->qscale_table = s->qp;
So the table is valid for an undefined amount of time? With the ref counting API, I believe this is not the desired behaviour.
Right, silly me. I will copy it. Is there something else?
Or can I copy this? Nothing in codebase allocate this or free it so I'm not sure whatever I do is correct. As current mp=qp filter does nothing I will simply remove it. This may force someone(if any) who actually care about it to finnaly fix it. (He can reuse this template freely.)
On date Wednesday 2013-09-18 18:34:36 +0000, Paul B Mahol encoded:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..e7cac2d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Quantization Parameter (QP) change filter.
Change video quantization parameters (QP). Possibly state why/how is this useful (MPlayer docs are pretty sparse on it).
+
+The filter accepts the following option:
options
+@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @option
Nit: @table @var
+@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equatition like:
equation
+@example +qp=2+2*sin(PI*qp) +@end example
Some meaningful examples are sorely needed. [...] -- FFmpeg = Funny & Fiendish Mega Practical Energized Guru
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table +@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + QPContext *s = ctx->priv; + AVBufferRef *out_qp_table_buf; + AVFrame *out; + const int8_t *in_qp_table; + int type, stride, ret; + + if (!s->qp_expr_str || ctx->is_disabled) + return ff_filter_frame(outlink, in); + + out_qp_table_buf = av_buffer_alloc(s->h * s->qstride); + if (!out_qp_table_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + + out = av_frame_clone(in); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + in_qp_table = av_frame_get_qp_table(in, &stride, &type); + av_frame_set_qp_table(out, out_qp_table_buf, s->qstride, type); + + if (in_qp_table) { + int y, x; + + for (y = 0; y < s->h; y++) + for (x = 0; x < s->qstride; x++) + out_qp_table_buf->data[x + s->qstride * y] = s->lut[129 + + ((int8_t)in_qp_table[x + stride * y])]; + } else { + int y, x, qp = s->lut[0]; + + for (y = 0; y < s->h; y++) + for (x = 0; x < s->qstride; x++) + out_qp_table_buf->data[x + s->qstride * y] = qp; + } + + ret = ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + return ret; +} + +static const AVFilterPad qp_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad qp_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter avfilter_vf_qp = { + .name = "qp", + .description = NULL_IF_CONFIG_SMALL("Change video quantization parameters."), + .priv_size = sizeof(QPContext), + .inputs = qp_inputs, + .outputs = qp_outputs, + .priv_class = &qp_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, +}; -- 1.7.11.2
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Many things microsoft did are stupid, but not doing something just because microsoft did it is even more stupid. If everything ms did were stupid they would be bankrupt already.
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct? This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
[...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Many things microsoft did are stupid, but not doing something just because microsoft did it is even more stupid. If everything ms did were stupid they would be bankrupt already.
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Avoid a single point of failure, be that a person or equipment.
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
[...]
-- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Avoid a single point of failure, be that a person or equipment.
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB It is dangerous to be right in matters on which the established authorities are wrong. -- Voltaire
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote:
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- doc/filters.texi | 32 ++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_qp.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 libavfilter/vf_qp.c
diff --git a/doc/filters.texi b/doc/filters.texi index 915f310..127885a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a chroma plane is to reduce CPU load and make pullup usable in realtime on slow machines. @end table
+@section qp + +Change video quantization parameters (QP). + +The filter accepts the following option: + +@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants: + +@table @var +@item known +1 if index is not 129, 0 otherwise. + +@item qp +Sequentional index starting from -129 to 128. +@end table + +@subsection Examples + +@itemize +@item +Some equation like: +@example +qp=2+2*sin(PI*qp) +@end example +@end itemize + @section removelogo
Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 198bf4c..5dc8389 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2825304..69e6cab 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -169,6 +169,7 @@ void avfilter_register_all(void) REGISTER_FILTER(PP, pp, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); + REGISTER_FILTER(QP, qp, vf); REGISTER_FILTER(REMOVELOGO, removelogo, vf); REGISTER_FILTER(ROTATE, rotate, vf); REGISTER_FILTER(SAB, sab, vf); diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c new file mode 100644 index 0000000..67fe2ec --- /dev/null +++ b/libavfilter/vf_qp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include "libavutil/eval.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct QPContext { + const AVClass *class; + char *qp_expr_str; + int8_t lut[257]; + int h, qstride; +} QPContext; + +#define OFFSET(x) offsetof(QPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption qp_options[] = { + { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(qp); + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QPContext *s = ctx->priv; + int i; + + if (!s->qp_expr_str) + return 0; + + s->h = (inlink->h + 15) >> 4; + s->qstride = (inlink->w + 15) >> 4; + for (i = -129; i < 128; i++) { + double var_values[] = { i != -129, i, 0 }; + static const char *var_names[] = { "known", "qp", NULL }; + double temp_val; + int ret; + + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, + var_names, var_values, + NULL, NULL, NULL, NULL, 0, 0, ctx); + if (ret < 0) + return ret; + + s->lut[i + 129] = lrintf(temp_val); + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks
OK, so I will commit this as is (with cloning removed) and leave it to others to improve/extend it. I can't as I'm missing testcase.
[...]
-- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
It is dangerous to be right in matters on which the established authorities are wrong. -- Voltaire
On Thu, Sep 19, 2013 at 08:48:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote: > Signed-off-by: Paul B Mahol <onemda@gmail.com> > --- > doc/filters.texi | 32 ++++++++++ > libavfilter/Makefile | 1 + > libavfilter/allfilters.c | 1 + > libavfilter/vf_qp.c | 152 > +++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 186 insertions(+) > create mode 100644 libavfilter/vf_qp.c > > diff --git a/doc/filters.texi b/doc/filters.texi > index 915f310..127885a 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to a > chroma > plane is to reduce CPU > load and make pullup usable in realtime on slow machines. > @end table > > +@section qp > + > +Change video quantization parameters (QP). > + > +The filter accepts the following option: > + > +@table @option > +@item qp > +Set expression for quantization parameter. > +@end table > + > +The expression is evaluated through the eval API and can contain, > among > others, > +the following constants: > + > +@table @var > +@item known > +1 if index is not 129, 0 otherwise. > + > +@item qp > +Sequentional index starting from -129 to 128. > +@end table > + > +@subsection Examples > + > +@itemize > +@item > +Some equation like: > +@example > +qp=2+2*sin(PI*qp) > +@end example > +@end itemize > + > @section removelogo > > Suppress a TV station logo, using an image file to determine which > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 198bf4c..5dc8389 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) += > vf_pixdesctest.o > OBJS-$(CONFIG_PP_FILTER) += vf_pp.o > OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o > dualinput.o > OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o > +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o > OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o > lavfutils.o vf_removelogo.o > OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o > OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += > vf_separatefields.o > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c > index 2825304..69e6cab 100644 > --- a/libavfilter/allfilters.c > +++ b/libavfilter/allfilters.c > @@ -169,6 +169,7 @@ void avfilter_register_all(void) > REGISTER_FILTER(PP, pp, vf); > REGISTER_FILTER(PSNR, psnr, vf); > REGISTER_FILTER(PULLUP, pullup, vf); > + REGISTER_FILTER(QP, qp, vf); > REGISTER_FILTER(REMOVELOGO, removelogo, vf); > REGISTER_FILTER(ROTATE, rotate, vf); > REGISTER_FILTER(SAB, sab, vf); > diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c > new file mode 100644 > index 0000000..67fe2ec > --- /dev/null > +++ b/libavfilter/vf_qp.c > @@ -0,0 +1,152 @@ > +/* > + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later > version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General > Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301 USA > + */ > + > +#include <math.h> > +#include "libavutil/eval.h" > +#include "libavutil/imgutils.h" > +#include "libavutil/pixdesc.h" > +#include "libavutil/opt.h" > +#include "avfilter.h" > +#include "formats.h" > +#include "internal.h" > +#include "video.h" > + > +typedef struct QPContext { > + const AVClass *class; > + char *qp_expr_str; > + int8_t lut[257]; > + int h, qstride; > +} QPContext; > + > +#define OFFSET(x) offsetof(QPContext, x) > +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM > + > +static const AVOption qp_options[] = { > + { "qp", "set qp expression", OFFSET(qp_expr_str), > AV_OPT_TYPE_STRING, > {.str=NULL}, 0, 0, FLAGS }, > + { NULL } > +}; > + > +AVFILTER_DEFINE_CLASS(qp); > + > +static int config_input(AVFilterLink *inlink) > +{ > + AVFilterContext *ctx = inlink->dst; > + QPContext *s = ctx->priv; > + int i; > + > + if (!s->qp_expr_str) > + return 0; > + > + s->h = (inlink->h + 15) >> 4; > + s->qstride = (inlink->w + 15) >> 4; > + for (i = -129; i < 128; i++) { > + double var_values[] = { i != -129, i, 0 }; > + static const char *var_names[] = { "known", "qp", NULL }; > + double temp_val; > + int ret; > + > + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, > + var_names, var_values, > + NULL, NULL, NULL, NULL, 0, 0, > ctx); > + if (ret < 0) > + return ret; > + > + s->lut[i + 129] = lrintf(temp_val); > + }
it could make sense to allow forcing the evaluating the expression for each macroblock that way it could be used to do spatial or temporal smoothing, depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks
OK, so I will commit this as is (with cloning removed) and leave it to others to improve/extend it. I can't as I'm missing testcase.
ping ill add a testcase once this is in git (that is once i remember because i will forget) [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Freedom in capitalist society always remains about the same as it was in ancient Greek republics: Freedom for slave owners. -- Vladimir Lenin
On 10/5/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 08:48:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote: > On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote: >> Signed-off-by: Paul B Mahol <onemda@gmail.com> >> --- >> doc/filters.texi | 32 ++++++++++ >> libavfilter/Makefile | 1 + >> libavfilter/allfilters.c | 1 + >> libavfilter/vf_qp.c | 152 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 186 insertions(+) >> create mode 100644 libavfilter/vf_qp.c >> >> diff --git a/doc/filters.texi b/doc/filters.texi >> index 915f310..127885a 100644 >> --- a/doc/filters.texi >> +++ b/doc/filters.texi >> @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} to >> a >> chroma >> plane is to reduce CPU >> load and make pullup usable in realtime on slow machines. >> @end table >> >> +@section qp >> + >> +Change video quantization parameters (QP). >> + >> +The filter accepts the following option: >> + >> +@table @option >> +@item qp >> +Set expression for quantization parameter. >> +@end table >> + >> +The expression is evaluated through the eval API and can >> contain, >> among >> others, >> +the following constants: >> + >> +@table @var >> +@item known >> +1 if index is not 129, 0 otherwise. >> + >> +@item qp >> +Sequentional index starting from -129 to 128. >> +@end table >> + >> +@subsection Examples >> + >> +@itemize >> +@item >> +Some equation like: >> +@example >> +qp=2+2*sin(PI*qp) >> +@end example >> +@end itemize >> + >> @section removelogo >> >> Suppress a TV station logo, using an image file to determine >> which >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile >> index 198bf4c..5dc8389 100644 >> --- a/libavfilter/Makefile >> +++ b/libavfilter/Makefile >> @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) >> += >> vf_pixdesctest.o >> OBJS-$(CONFIG_PP_FILTER) += vf_pp.o >> OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o >> dualinput.o >> OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o >> +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o >> OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o >> lswsutils.o >> lavfutils.o vf_removelogo.o >> OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o >> OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += >> vf_separatefields.o >> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c >> index 2825304..69e6cab 100644 >> --- a/libavfilter/allfilters.c >> +++ b/libavfilter/allfilters.c >> @@ -169,6 +169,7 @@ void avfilter_register_all(void) >> REGISTER_FILTER(PP, pp, vf); >> REGISTER_FILTER(PSNR, psnr, vf); >> REGISTER_FILTER(PULLUP, pullup, vf); >> + REGISTER_FILTER(QP, qp, vf); >> REGISTER_FILTER(REMOVELOGO, removelogo, vf); >> REGISTER_FILTER(ROTATE, rotate, vf); >> REGISTER_FILTER(SAB, sab, vf); >> diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c >> new file mode 100644 >> index 0000000..67fe2ec >> --- /dev/null >> +++ b/libavfilter/vf_qp.c >> @@ -0,0 +1,152 @@ >> +/* >> + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> >> + * >> + * This file is part of FFmpeg. >> + * >> + * FFmpeg is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2.1 of the License, or (at your option) any later >> version. >> + * >> + * FFmpeg is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty >> of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See >> the >> GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General >> Public >> + * License along with FFmpeg; if not, write to the Free >> Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, >> MA >> 02110-1301 USA >> + */ >> + >> +#include <math.h> >> +#include "libavutil/eval.h" >> +#include "libavutil/imgutils.h" >> +#include "libavutil/pixdesc.h" >> +#include "libavutil/opt.h" >> +#include "avfilter.h" >> +#include "formats.h" >> +#include "internal.h" >> +#include "video.h" >> + >> +typedef struct QPContext { >> + const AVClass *class; >> + char *qp_expr_str; >> + int8_t lut[257]; >> + int h, qstride; >> +} QPContext; >> + >> +#define OFFSET(x) offsetof(QPContext, x) >> +#define FLAGS >> AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM >> + >> +static const AVOption qp_options[] = { >> + { "qp", "set qp expression", OFFSET(qp_expr_str), >> AV_OPT_TYPE_STRING, >> {.str=NULL}, 0, 0, FLAGS }, >> + { NULL } >> +}; >> + >> +AVFILTER_DEFINE_CLASS(qp); >> + >> +static int config_input(AVFilterLink *inlink) >> +{ >> + AVFilterContext *ctx = inlink->dst; >> + QPContext *s = ctx->priv; >> + int i; >> + >> + if (!s->qp_expr_str) >> + return 0; >> + >> + s->h = (inlink->h + 15) >> 4; >> + s->qstride = (inlink->w + 15) >> 4; >> + for (i = -129; i < 128; i++) { >> + double var_values[] = { i != -129, i, 0 }; >> + static const char *var_names[] = { "known", "qp", NULL >> }; >> + double temp_val; >> + int ret; >> + >> + ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, >> + var_names, var_values, >> + NULL, NULL, NULL, NULL, 0, >> 0, >> ctx); >> + if (ret < 0) >> + return ret; >> + >> + s->lut[i + 129] = lrintf(temp_val); >> + } > > it could make sense to allow forcing the evaluating the > expression > for > each macroblock > that way it could be used to do spatial or temporal smoothing, > depend on frame number of do add a random value
Gread idea, but becaues I can't compare it with broken mp=qp, I want to know is current code (use of API) correct?
This patch is not about adding new (non-trivial/easy) features, one can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks
OK, so I will commit this as is (with cloning removed) and leave it to others to improve/extend it. I can't as I'm missing testcase.
ping ill add a testcase once this is in git (that is once i remember because i will forget)
You, or anyone can take this and modify it and push it.
On 10/5/13, Paul B Mahol <onemda@gmail.com> wrote:
On 10/5/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 08:48:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote: > On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote: > > On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote: > >> Signed-off-by: Paul B Mahol <onemda@gmail.com> > >> --- > >> doc/filters.texi | 32 ++++++++++ > >> libavfilter/Makefile | 1 + > >> libavfilter/allfilters.c | 1 + > >> libavfilter/vf_qp.c | 152 > >> +++++++++++++++++++++++++++++++++++++++++++++++ > >> 4 files changed, 186 insertions(+) > >> create mode 100644 libavfilter/vf_qp.c > >> > >> diff --git a/doc/filters.texi b/doc/filters.texi > >> index 915f310..127885a 100644 > >> --- a/doc/filters.texi > >> +++ b/doc/filters.texi > >> @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} > >> to > >> a > >> chroma > >> plane is to reduce CPU > >> load and make pullup usable in realtime on slow machines. > >> @end table > >> > >> +@section qp > >> + > >> +Change video quantization parameters (QP). > >> + > >> +The filter accepts the following option: > >> + > >> +@table @option > >> +@item qp > >> +Set expression for quantization parameter. > >> +@end table > >> + > >> +The expression is evaluated through the eval API and can > >> contain, > >> among > >> others, > >> +the following constants: > >> + > >> +@table @var > >> +@item known > >> +1 if index is not 129, 0 otherwise. > >> + > >> +@item qp > >> +Sequentional index starting from -129 to 128. > >> +@end table > >> + > >> +@subsection Examples > >> + > >> +@itemize > >> +@item > >> +Some equation like: > >> +@example > >> +qp=2+2*sin(PI*qp) > >> +@end example > >> +@end itemize > >> + > >> @section removelogo > >> > >> Suppress a TV station logo, using an image file to determine > >> which > >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile > >> index 198bf4c..5dc8389 100644 > >> --- a/libavfilter/Makefile > >> +++ b/libavfilter/Makefile > >> @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) > >> += > >> vf_pixdesctest.o > >> OBJS-$(CONFIG_PP_FILTER) += vf_pp.o > >> OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o > >> dualinput.o > >> OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o > >> +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o > >> OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o > >> lswsutils.o > >> lavfutils.o vf_removelogo.o > >> OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o > >> OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += > >> vf_separatefields.o > >> diff --git a/libavfilter/allfilters.c > >> b/libavfilter/allfilters.c > >> index 2825304..69e6cab 100644 > >> --- a/libavfilter/allfilters.c > >> +++ b/libavfilter/allfilters.c > >> @@ -169,6 +169,7 @@ void avfilter_register_all(void) > >> REGISTER_FILTER(PP, pp, vf); > >> REGISTER_FILTER(PSNR, psnr, vf); > >> REGISTER_FILTER(PULLUP, pullup, vf); > >> + REGISTER_FILTER(QP, qp, vf); > >> REGISTER_FILTER(REMOVELOGO, removelogo, vf); > >> REGISTER_FILTER(ROTATE, rotate, vf); > >> REGISTER_FILTER(SAB, sab, vf); > >> diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c > >> new file mode 100644 > >> index 0000000..67fe2ec > >> --- /dev/null > >> +++ b/libavfilter/vf_qp.c > >> @@ -0,0 +1,152 @@ > >> +/* > >> + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> > >> + * > >> + * This file is part of FFmpeg. > >> + * > >> + * FFmpeg is free software; you can redistribute it and/or > >> + * modify it under the terms of the GNU Lesser General Public > >> + * License as published by the Free Software Foundation; > >> either > >> + * version 2.1 of the License, or (at your option) any later > >> version. > >> + * > >> + * FFmpeg is distributed in the hope that it will be useful, > >> + * but WITHOUT ANY WARRANTY; without even the implied warranty > >> of > >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > >> the > >> GNU > >> + * Lesser General Public License for more details. > >> + * > >> + * You should have received a copy of the GNU Lesser General > >> Public > >> + * License along with FFmpeg; if not, write to the Free > >> Software > >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > >> MA > >> 02110-1301 USA > >> + */ > >> + > >> +#include <math.h> > >> +#include "libavutil/eval.h" > >> +#include "libavutil/imgutils.h" > >> +#include "libavutil/pixdesc.h" > >> +#include "libavutil/opt.h" > >> +#include "avfilter.h" > >> +#include "formats.h" > >> +#include "internal.h" > >> +#include "video.h" > >> + > >> +typedef struct QPContext { > >> + const AVClass *class; > >> + char *qp_expr_str; > >> + int8_t lut[257]; > >> + int h, qstride; > >> +} QPContext; > >> + > >> +#define OFFSET(x) offsetof(QPContext, x) > >> +#define FLAGS > >> AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM > >> + > >> +static const AVOption qp_options[] = { > >> + { "qp", "set qp expression", OFFSET(qp_expr_str), > >> AV_OPT_TYPE_STRING, > >> {.str=NULL}, 0, 0, FLAGS }, > >> + { NULL } > >> +}; > >> + > >> +AVFILTER_DEFINE_CLASS(qp); > >> + > >> +static int config_input(AVFilterLink *inlink) > >> +{ > >> + AVFilterContext *ctx = inlink->dst; > >> + QPContext *s = ctx->priv; > >> + int i; > >> + > >> + if (!s->qp_expr_str) > >> + return 0; > >> + > >> + s->h = (inlink->h + 15) >> 4; > >> + s->qstride = (inlink->w + 15) >> 4; > >> + for (i = -129; i < 128; i++) { > >> + double var_values[] = { i != -129, i, 0 }; > >> + static const char *var_names[] = { "known", "qp", NULL > >> }; > >> + double temp_val; > >> + int ret; > >> + > >> + ret = av_expr_parse_and_eval(&temp_val, > >> s->qp_expr_str, > >> + var_names, var_values, > >> + NULL, NULL, NULL, NULL, > >> 0, > >> 0, > >> ctx); > >> + if (ret < 0) > >> + return ret; > >> + > >> + s->lut[i + 129] = lrintf(temp_val); > >> + } > > > > it could make sense to allow forcing the evaluating the > > expression > > for > > each macroblock > > that way it could be used to do spatial or temporal smoothing, > > depend on frame number of do add a random value > > Gread idea, but becaues I can't compare it with broken mp=qp, I > want > to > know > is current code (use of API) correct? > > This patch is not about adding new (non-trivial/easy) features, > one > can do it freely later.
the API use should be ok but i dont think you need to clone the frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks
OK, so I will commit this as is (with cloning removed) and leave it to others to improve/extend it. I can't as I'm missing testcase.
ping ill add a testcase once this is in git (that is once i remember because i will forget)
You, or anyone can take this and modify it and push it.
ping
On Wed, Jan 14, 2015 at 09:56:36AM +0000, Paul B Mahol wrote:
On 10/5/13, Paul B Mahol <onemda@gmail.com> wrote:
On 10/5/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 08:48:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote:
On Thu, Sep 19, 2013 at 06:00:55PM +0000, Paul B Mahol wrote:
On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote: > On Thu, Sep 19, 2013 at 10:49:41AM +0000, Paul B Mahol wrote: >> On 9/19/13, Michael Niedermayer <michaelni@gmx.at> wrote: >> > On Wed, Sep 18, 2013 at 11:57:55PM +0000, Paul B Mahol wrote: >> >> Signed-off-by: Paul B Mahol <onemda@gmail.com> >> >> --- >> >> doc/filters.texi | 32 ++++++++++ >> >> libavfilter/Makefile | 1 + >> >> libavfilter/allfilters.c | 1 + >> >> libavfilter/vf_qp.c | 152 >> >> +++++++++++++++++++++++++++++++++++++++++++++++ >> >> 4 files changed, 186 insertions(+) >> >> create mode 100644 libavfilter/vf_qp.c >> >> >> >> diff --git a/doc/filters.texi b/doc/filters.texi >> >> index 915f310..127885a 100644 >> >> --- a/doc/filters.texi >> >> +++ b/doc/filters.texi >> >> @@ -6236,6 +6236,38 @@ The main purpose of setting @option{mp} >> >> to >> >> a >> >> chroma >> >> plane is to reduce CPU >> >> load and make pullup usable in realtime on slow machines. >> >> @end table >> >> >> >> +@section qp >> >> + >> >> +Change video quantization parameters (QP). >> >> + >> >> +The filter accepts the following option: >> >> + >> >> +@table @option >> >> +@item qp >> >> +Set expression for quantization parameter. >> >> +@end table >> >> + >> >> +The expression is evaluated through the eval API and can >> >> contain, >> >> among >> >> others, >> >> +the following constants: >> >> + >> >> +@table @var >> >> +@item known >> >> +1 if index is not 129, 0 otherwise. >> >> + >> >> +@item qp >> >> +Sequentional index starting from -129 to 128. >> >> +@end table >> >> + >> >> +@subsection Examples >> >> + >> >> +@itemize >> >> +@item >> >> +Some equation like: >> >> +@example >> >> +qp=2+2*sin(PI*qp) >> >> +@end example >> >> +@end itemize >> >> + >> >> @section removelogo >> >> >> >> Suppress a TV station logo, using an image file to determine >> >> which >> >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile >> >> index 198bf4c..5dc8389 100644 >> >> --- a/libavfilter/Makefile >> >> +++ b/libavfilter/Makefile >> >> @@ -174,6 +174,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER) >> >> += >> >> vf_pixdesctest.o >> >> OBJS-$(CONFIG_PP_FILTER) += vf_pp.o >> >> OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o >> >> dualinput.o >> >> OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o >> >> +OBJS-$(CONFIG_QP_FILTER) += vf_qp.o >> >> OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o >> >> lswsutils.o >> >> lavfutils.o vf_removelogo.o >> >> OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o >> >> OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += >> >> vf_separatefields.o >> >> diff --git a/libavfilter/allfilters.c >> >> b/libavfilter/allfilters.c >> >> index 2825304..69e6cab 100644 >> >> --- a/libavfilter/allfilters.c >> >> +++ b/libavfilter/allfilters.c >> >> @@ -169,6 +169,7 @@ void avfilter_register_all(void) >> >> REGISTER_FILTER(PP, pp, vf); >> >> REGISTER_FILTER(PSNR, psnr, vf); >> >> REGISTER_FILTER(PULLUP, pullup, vf); >> >> + REGISTER_FILTER(QP, qp, vf); >> >> REGISTER_FILTER(REMOVELOGO, removelogo, vf); >> >> REGISTER_FILTER(ROTATE, rotate, vf); >> >> REGISTER_FILTER(SAB, sab, vf); >> >> diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c >> >> new file mode 100644 >> >> index 0000000..67fe2ec >> >> --- /dev/null >> >> +++ b/libavfilter/vf_qp.c >> >> @@ -0,0 +1,152 @@ >> >> +/* >> >> + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> >> >> + * >> >> + * This file is part of FFmpeg. >> >> + * >> >> + * FFmpeg is free software; you can redistribute it and/or >> >> + * modify it under the terms of the GNU Lesser General Public >> >> + * License as published by the Free Software Foundation; >> >> either >> >> + * version 2.1 of the License, or (at your option) any later >> >> version. >> >> + * >> >> + * FFmpeg is distributed in the hope that it will be useful, >> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty >> >> of >> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See >> >> the >> >> GNU >> >> + * Lesser General Public License for more details. >> >> + * >> >> + * You should have received a copy of the GNU Lesser General >> >> Public >> >> + * License along with FFmpeg; if not, write to the Free >> >> Software >> >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, >> >> MA >> >> 02110-1301 USA >> >> + */ >> >> + >> >> +#include <math.h> >> >> +#include "libavutil/eval.h" >> >> +#include "libavutil/imgutils.h" >> >> +#include "libavutil/pixdesc.h" >> >> +#include "libavutil/opt.h" >> >> +#include "avfilter.h" >> >> +#include "formats.h" >> >> +#include "internal.h" >> >> +#include "video.h" >> >> + >> >> +typedef struct QPContext { >> >> + const AVClass *class; >> >> + char *qp_expr_str; >> >> + int8_t lut[257]; >> >> + int h, qstride; >> >> +} QPContext; >> >> + >> >> +#define OFFSET(x) offsetof(QPContext, x) >> >> +#define FLAGS >> >> AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM >> >> + >> >> +static const AVOption qp_options[] = { >> >> + { "qp", "set qp expression", OFFSET(qp_expr_str), >> >> AV_OPT_TYPE_STRING, >> >> {.str=NULL}, 0, 0, FLAGS }, >> >> + { NULL } >> >> +}; >> >> + >> >> +AVFILTER_DEFINE_CLASS(qp); >> >> + >> >> +static int config_input(AVFilterLink *inlink) >> >> +{ >> >> + AVFilterContext *ctx = inlink->dst; >> >> + QPContext *s = ctx->priv; >> >> + int i; >> >> + >> >> + if (!s->qp_expr_str) >> >> + return 0; >> >> + >> >> + s->h = (inlink->h + 15) >> 4; >> >> + s->qstride = (inlink->w + 15) >> 4; >> >> + for (i = -129; i < 128; i++) { >> >> + double var_values[] = { i != -129, i, 0 }; >> >> + static const char *var_names[] = { "known", "qp", NULL >> >> }; >> >> + double temp_val; >> >> + int ret; >> >> + >> >> + ret = av_expr_parse_and_eval(&temp_val, >> >> s->qp_expr_str, >> >> + var_names, var_values, >> >> + NULL, NULL, NULL, NULL, >> >> 0, >> >> 0, >> >> ctx); >> >> + if (ret < 0) >> >> + return ret; >> >> + >> >> + s->lut[i + 129] = lrintf(temp_val); >> >> + } >> > >> > it could make sense to allow forcing the evaluating the >> > expression >> > for >> > each macroblock >> > that way it could be used to do spatial or temporal smoothing, >> > depend on frame number of do add a random value >> >> Gread idea, but becaues I can't compare it with broken mp=qp, I >> want >> to >> know >> is current code (use of API) correct? >> >> This patch is not about adding new (non-trivial/easy) features, >> one >> can do it freely later. > > the API use should be ok but i dont think you need to clone the > frame
So i can just overwrite it, even if frame is not writtable?
you can set a new table, you cant write into an existing table without some additional checks
OK, so I will commit this as is (with cloning removed) and leave it to others to improve/extend it. I can't as I'm missing testcase.
ping ill add a testcase once this is in git (that is once i remember because i will forget)
You, or anyone can take this and modify it and push it.
ping
patch applied test added thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Concerning the gods, I have no means of knowing whether they exist or not or of what sort they may be, because of the obscurity of the subject, and the brevity of human life -- Protagoras
On 9/19/2013 12:57 AM, Paul B Mahol wrote:
+@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants:
This doesn't really make clear what it does of why it's useful... - Derek
On 9/19/13, Derek Buitenhuis <derek.buitenhuis@gmail.com> wrote:
On 9/19/2013 12:57 AM, Paul B Mahol wrote:
+@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants:
This doesn't really make clear what it does of why it's useful...
If I know I would write one. Documentation in mplayer is also non-existent.
On 9/19/2013 1:05 PM, Paul B Mahol wrote:
If I know I would write one.
Documentation in mplayer is also non-existent.
How did we know it was even worth porting if we don't know properly what it does? - Derek
Derek Buitenhuis <derek.buitenhuis@gmail.com> wrote:
On 9/19/2013 12:57 AM, Paul B Mahol wrote:
+@table @option +@item qp +Set expression for quantization parameter. +@end table + +The expression is evaluated through the eval API and can contain, among others, +the following constants:
This doesn't really make clear what it does of why it's useful...
Out of memory, so there might be inaccuracies: It modifies the qp table. Those qp values are per macroblock and are for example used by deblocking filters like spp to decide on the strength of deblocking etc. So this fitter allows to fine-tune their behaviour. It could (but not sure if it is) also be used as a hint for encoders, blocks with high qp are likely to have mostly artefacts as details and wasting bits on representing them is pointless. For decoders that provide a broken/wrongly scaled qp table this was in MPlayer also a way to make the deblocking filters at least somewhat work.
participants (6)
-
Clément Bœsch -
Derek Buitenhuis -
Michael Niedermayer -
Paul B Mahol -
Reimar Döffinger -
Stefano Sabatini