Browse code

avfilter/geq: rgb support

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2013/04/23 22:46:51
Showing 1 changed files
... ...
@@ -35,10 +35,11 @@
35 35
 typedef struct {
36 36
     const AVClass *class;
37 37
     AVExpr *e[4];               ///< expressions for each plane
38
-    char *expr_str[4];          ///< expression strings for each plane
38
+    char *expr_str[4+3];        ///< expression strings for each plane
39 39
     AVFrame *picref;            ///< current input buffer
40 40
     int hsub, vsub;             ///< chroma subsampling
41 41
     int planes;                 ///< number of planes
42
+    int is_rgb;
42 43
 } GEQContext;
43 44
 
44 45
 #define OFFSET(x) offsetof(GEQContext, x)
... ...
@@ -49,6 +50,10 @@ static const AVOption geq_options[] = {
49 49
     { "cb_expr",    "set chroma blue expression", OFFSET(expr_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
50 50
     { "cr_expr",    "set chroma red expression",  OFFSET(expr_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
51 51
     { "alpha_expr", "set alpha expression",       OFFSET(expr_str[3]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
52
+
53
+    { "r",          "set red expression",   OFFSET(expr_str[6]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
54
+    { "g",          "set green expression", OFFSET(expr_str[4]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
55
+    { "b",          "set blue expression",  OFFSET(expr_str[5]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
52 56
     {NULL},
53 57
 };
54 58
 
... ...
@@ -92,8 +97,15 @@ static av_cold int geq_init(AVFilterContext *ctx)
92 92
     GEQContext *geq = ctx->priv;
93 93
     int plane, ret = 0;
94 94
 
95
-    if (!geq->expr_str[0]) {
96
-        av_log(ctx, AV_LOG_ERROR, "Luminance expression is mandatory\n");
95
+    if (!geq->expr_str[0] && !geq->expr_str[4] && !geq->expr_str[5] && !geq->expr_str[6]) {
96
+        av_log(ctx, AV_LOG_ERROR, "A luminance or RGB expression is mandatory\n");
97
+        ret = AVERROR(EINVAL);
98
+        goto end;
99
+    }
100
+    geq->is_rgb = !geq->expr_str[0];
101
+
102
+    if ((geq->expr_str[0] || geq->expr_str[1] || geq->expr_str[2]) && (geq->expr_str[4] || geq->expr_str[5] || geq->expr_str[6])) {
103
+        av_log(ctx, AV_LOG_ERROR, "Either YCbCr or RGB but not both must be specified\n");
97 104
         ret = AVERROR(EINVAL);
98 105
         goto end;
99 106
     }
... ...
@@ -110,18 +122,29 @@ static av_cold int geq_init(AVFilterContext *ctx)
110 110
 
111 111
     if (!geq->expr_str[3])
112 112
         geq->expr_str[3] = av_strdup("255");
113
-
114
-    if (!geq->expr_str[1] || !geq->expr_str[2] || !geq->expr_str[3]) {
113
+    if (!geq->expr_str[4])
114
+        geq->expr_str[4] = av_strdup("g(X,Y)");
115
+    if (!geq->expr_str[5])
116
+        geq->expr_str[5] = av_strdup("b(X,Y)");
117
+    if (!geq->expr_str[6])
118
+        geq->expr_str[6] = av_strdup("r(X,Y)");
119
+
120
+    if (geq->is_rgb ?
121
+            (!geq->expr_str[4] || !geq->expr_str[5] || !geq->expr_str[6])
122
+                    :
123
+            (!geq->expr_str[1] || !geq->expr_str[2] || !geq->expr_str[3])) {
115 124
         ret = AVERROR(ENOMEM);
116 125
         goto end;
117 126
     }
118 127
 
119 128
     for (plane = 0; plane < 4; plane++) {
120 129
         static double (*p[])(void *, double, double) = { lum, cb, cr, alpha };
121
-        static const char *const func2_names[]    = { "lum", "cb", "cr", "alpha", "p", NULL };
130
+        static const char *const func2_yuv_names[]    = { "lum", "cb", "cr", "alpha", "p", NULL };
131
+        static const char *const func2_rgb_names[]    = { "g", "b", "r", "alpha", "p", NULL };
132
+        const char *const *func2_names       = geq->is_rgb ? func2_rgb_names : func2_yuv_names;
122 133
         double (*func2[])(void *, double, double) = { lum, cb, cr, alpha, p[plane], NULL };
123 134
 
124
-        ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane], var_names,
135
+        ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names,
125 136
                             NULL, NULL, func2_names, func2, 0, ctx);
126 137
         if (ret < 0)
127 138
             break;
... ...
@@ -133,14 +156,22 @@ end:
133 133
 
134 134
 static int geq_query_formats(AVFilterContext *ctx)
135 135
 {
136
-    static const enum PixelFormat pix_fmts[] = {
136
+    GEQContext *geq = ctx->priv;
137
+    static const enum PixelFormat yuv_pix_fmts[] = {
137 138
         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
138 139
         AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,  AV_PIX_FMT_YUV440P,
139 140
         AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
140 141
         AV_PIX_FMT_GRAY8,
141 142
         AV_PIX_FMT_NONE
142 143
     };
143
-    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
144
+    static const enum PixelFormat rgb_pix_fmts[] = {
145
+        AV_PIX_FMT_GBRP,
146
+        AV_PIX_FMT_NONE
147
+    };
148
+    if (geq->is_rgb) {
149
+        ff_set_common_formats(ctx, ff_make_format_list(rgb_pix_fmts));
150
+    } else
151
+        ff_set_common_formats(ctx, ff_make_format_list(yuv_pix_fmts));
144 152
     return 0;
145 153
 }
146 154