[FFmpeg-cvslog] lavfi/geq: improve support for formats with alpha plane

Paul B Mahol git at videolan.org
Mon Feb 25 13:58:39 CET 2013


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Feb 25 09:14:24 2013 +0000| [eac93932b0118756448932a3622a136ecf022c88] | committer: Paul B Mahol

lavfi/geq: improve support for formats with alpha plane

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=eac93932b0118756448932a3622a136ecf022c88
---

 doc/filters.texi     |   17 ++++++++++++-----
 libavfilter/vf_geq.c |   45 ++++++++++++++++++++++++++++-----------------
 2 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 5fda913..bcbe21a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -3047,7 +3047,7 @@ For more information see:
 
 @section geq
 
-The filter takes one, two or three equations as parameter, separated by ':'.
+The filter takes one, two, three or four equations as parameter, separated by ':'.
 The first equation is mandatory and applies to the luma plane. The two
 following are respectively for chroma blue and chroma red planes.
 
@@ -3060,11 +3060,14 @@ the luminance expression
 the chrominance blue expression
 @item cr_expr
 the chrominance red expression
+ at item alpha_expr
+the alpha expression
 @end table
 
 If one of the chrominance expression is not defined, it falls back on the other
-one. If none of them are specified, they will evaluate the luminance
-expression.
+one. If no alpha expression is specified it will evaluate to opaque value.
+If none of chrominance expressions are
+specified, they will evaluate the luminance expression.
 
 The expressions can use the following variables and functions:
 
@@ -3097,11 +3100,15 @@ plane.
 
 @item cb(x, y)
 Return the value of the pixel at location (@var{x}, at var{y}) of the
-blue-difference chroma plane.
+blue-difference chroma plane. Returns 0 if there is no such plane.
 
 @item cr(x, y)
 Return the value of the pixel at location (@var{x}, at var{y}) of the
-red-difference chroma plane.
+red-difference chroma plane. Returns 0 if there is no such plane.
+
+ at item alpha(x, y)
+Return the value of the pixel at location (@var{x}, at var{y}) of the alpha
+plane. Returns 0 if there is no such plane.
 @end table
 
 For functions, if @var{x} and @var{y} are outside the area, the value will be
diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
index 2f7b50b..72ecda0 100644
--- a/libavfilter/vf_geq.c
+++ b/libavfilter/vf_geq.c
@@ -34,20 +34,22 @@
 
 typedef struct {
     const AVClass *class;
-    AVExpr *e[3];               ///< expressions for each plane
-    char *expr_str[3];          ///< expression strings for each plane
+    AVExpr *e[4];               ///< expressions for each plane
+    char *expr_str[4];          ///< expression strings for each plane
     int framenum;               ///< frame counter
     AVFilterBufferRef *picref;  ///< current input buffer
     int hsub, vsub;             ///< chroma subsampling
+    int planes;                 ///< number of planes
 } GEQContext;
 
 #define OFFSET(x) offsetof(GEQContext, x)
 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 
 static const AVOption geq_options[] = {
-    { "lum_expr",   "set luminance expression",   OFFSET(expr_str),                   AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
-    { "cb_expr",    "set chroma blue expression", OFFSET(expr_str) +   sizeof(char*), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
-    { "cr_expr",    "set chroma red expression",  OFFSET(expr_str) + 2*sizeof(char*), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+    { "lum_expr",   "set luminance expression",   OFFSET(expr_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+    { "cb_expr",    "set chroma blue expression", OFFSET(expr_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+    { "cr_expr",    "set chroma red expression",  OFFSET(expr_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+    { "alpha_expr", "set alpha expression",       OFFSET(expr_str[3]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
     {NULL},
 };
 
@@ -60,8 +62,11 @@ static inline double getpix(void *priv, double x, double y, int plane)
     AVFilterBufferRef *picref = geq->picref;
     const uint8_t *src = picref->data[plane];
     const int linesize = picref->linesize[plane];
-    const int w = picref->video->w >> (plane ? geq->hsub : 0);
-    const int h = picref->video->h >> (plane ? geq->vsub : 0);
+    const int w = picref->video->w >> ((plane == 1 || plane == 2) ? geq->hsub : 0);
+    const int h = picref->video->h >> ((plane == 1 || plane == 2) ? geq->vsub : 0);
+
+    if (!src)
+        return 0;
 
     xi = x = av_clipf(x, 0, w - 2);
     yi = y = av_clipf(y, 0, h - 2);
@@ -78,6 +83,7 @@ static inline double getpix(void *priv, double x, double y, int plane)
 static double lum(void *priv, double x, double y) { return getpix(priv, x, y, 0); }
 static double  cb(void *priv, double x, double y) { return getpix(priv, x, y, 1); }
 static double  cr(void *priv, double x, double y) { return getpix(priv, x, y, 2); }
+static double alpha(void *priv, double x, double y) { return getpix(priv, x, y, 3); }
 
 static const char *const var_names[] = {   "X",   "Y",   "W",   "H",   "N",   "SW",   "SH",   "T",        NULL };
 enum                                   { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB };
@@ -86,7 +92,7 @@ static av_cold int geq_init(AVFilterContext *ctx, const char *args)
 {
     GEQContext *geq = ctx->priv;
     int plane, ret = 0;
-    static const char *shorthand[] = { "lum_expr", "cb_expr", "cr_expr", NULL };
+    static const char *shorthand[] = { "lum_expr", "cb_expr", "cr_expr", "alpha_expr", NULL };
 
     geq->class = &geq_class;
     av_opt_set_defaults(geq);
@@ -110,15 +116,18 @@ static av_cold int geq_init(AVFilterContext *ctx, const char *args)
         if (!geq->expr_str[2]) geq->expr_str[2] = av_strdup(geq->expr_str[1]);
     }
 
-    if (!geq->expr_str[1] || !geq->expr_str[2]) {
+    if (!geq->expr_str[3])
+        geq->expr_str[3] = av_strdup("255");
+
+    if (!geq->expr_str[1] || !geq->expr_str[2] || !geq->expr_str[3]) {
         ret = AVERROR(ENOMEM);
         goto end;
     }
 
-    for (plane = 0; plane < 3; plane++) {
-        static double (*p[])(void *, double, double) = { lum, cb, cr };
-        static const char *const func2_names[]    = { "lum", "cb", "cr", "p", NULL };
-        double (*func2[])(void *, double, double) = { lum, cb, cr, p[plane], NULL };
+    for (plane = 0; plane < 4; plane++) {
+        static double (*p[])(void *, double, double) = { lum, cb, cr, alpha };
+        static const char *const func2_names[]    = { "lum", "cb", "cr", "alpha", "p", NULL };
+        double (*func2[])(void *, double, double) = { lum, cb, cr, alpha, p[plane], NULL };
 
         ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane], var_names,
                             NULL, NULL, func2_names, func2, 0, ctx);
@@ -135,7 +144,8 @@ static int geq_query_formats(AVFilterContext *ctx)
     static const enum PixelFormat pix_fmts[] = {
         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
         AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,  AV_PIX_FMT_YUV440P,
-        AV_PIX_FMT_YUVA420P,
+        AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
+        AV_PIX_FMT_GRAY8,
         AV_PIX_FMT_NONE
     };
     ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
@@ -149,6 +159,7 @@ static int geq_config_props(AVFilterLink *inlink)
 
     geq->hsub = desc->log2_chroma_w;
     geq->vsub = desc->log2_chroma_h;
+    geq->planes = desc->nb_components;
     return 0;
 }
 
@@ -171,12 +182,12 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
     }
     avfilter_copy_buffer_ref_props(out, in);
 
-    for (plane = 0; plane < 3; plane++) {
+    for (plane = 0; plane < geq->planes && out->data[plane]; plane++) {
         int x, y;
         uint8_t *dst = out->data[plane];
         const int linesize = out->linesize[plane];
-        const int w = inlink->w >> (plane ? geq->hsub : 0);
-        const int h = inlink->h >> (plane ? geq->vsub : 0);
+        const int w = inlink->w >> ((plane == 1 || plane == 2) ? geq->hsub : 0);
+        const int h = inlink->h >> ((plane == 1 || plane == 2) ? geq->vsub : 0);
 
         values[VAR_W]  = w;
         values[VAR_H]  = h;



More information about the ffmpeg-cvslog mailing list