Browse code

lavfi/extractplanes: packed rgb support

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

Paul B Mahol authored on 2013/05/09 03:24:39
Showing 1 changed files
... ...
@@ -23,6 +23,7 @@
23 23
 #include "libavutil/opt.h"
24 24
 #include "libavutil/pixdesc.h"
25 25
 #include "avfilter.h"
26
+#include "drawutils.h"
26 27
 #include "internal.h"
27 28
 
28 29
 #define PLANE_R 0x01
... ...
@@ -38,6 +39,9 @@ typedef struct {
38 38
     int requested_planes;
39 39
     int map[4];
40 40
     int linesize[4];
41
+    int is_packed_rgb;
42
+    int depth;
43
+    int step;
41 44
 } ExtractPlanesContext;
42 45
 
43 46
 #define OFFSET(x) offsetof(ExtractPlanesContext, x)
... ...
@@ -47,8 +51,8 @@ static const AVOption extractplanes_options[] = {
47 47
     {      "y", "set luma plane",  0, AV_OPT_TYPE_CONST, {.i64=PLANE_Y}, 0, 0, FLAGS, "flags"},
48 48
     {      "u", "set u plane",     0, AV_OPT_TYPE_CONST, {.i64=PLANE_U}, 0, 0, FLAGS, "flags"},
49 49
     {      "v", "set v plane",     0, AV_OPT_TYPE_CONST, {.i64=PLANE_V}, 0, 0, FLAGS, "flags"},
50
-    {      "g", "set green plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_G}, 0, 0, FLAGS, "flags"},
51 50
     {      "r", "set red plane",   0, AV_OPT_TYPE_CONST, {.i64=PLANE_R}, 0, 0, FLAGS, "flags"},
51
+    {      "g", "set green plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_G}, 0, 0, FLAGS, "flags"},
52 52
     {      "b", "set blue plane",  0, AV_OPT_TYPE_CONST, {.i64=PLANE_B}, 0, 0, FLAGS, "flags"},
53 53
     {      "a", "set alpha plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_A}, 0, 0, FLAGS, "flags"},
54 54
     { NULL }
... ...
@@ -75,6 +79,13 @@ static int query_formats(AVFilterContext *ctx)
75 75
         AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
76 76
         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A,
77 77
         AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE,
78
+        AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
79
+        AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
80
+        AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
81
+        AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
82
+        AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
83
+        AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
84
+        AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE,
78 85
         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
79 86
         AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE,
80 87
         AV_PIX_FMT_GBRAP16LE, AV_PIX_FMT_GBRAP16BE,
... ...
@@ -125,7 +136,8 @@ static int config_input(AVFilterLink *inlink)
125 125
     AVFilterContext *ctx = inlink->dst;
126 126
     ExtractPlanesContext *e = ctx->priv;
127 127
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
128
-    int plane_avail, ret;
128
+    int plane_avail, ret, i;
129
+    uint8_t rgba_map[4];
129 130
 
130 131
     plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B :
131 132
                                                  PLANE_Y |
... ...
@@ -138,6 +150,15 @@ static int config_input(AVFilterLink *inlink)
138 138
     if ((ret = av_image_fill_linesizes(e->linesize, inlink->format, inlink->w)) < 0)
139 139
         return ret;
140 140
 
141
+    e->depth = (desc->comp[0].depth_minus1 + 1) >> 3;
142
+    e->step = av_get_padded_bits_per_pixel(desc) >> 3;
143
+    e->is_packed_rgb = !(desc->flags & PIX_FMT_PLANAR);
144
+    if (desc->flags & PIX_FMT_RGB) {
145
+        ff_fill_rgba_map(rgba_map, inlink->format);
146
+        for (i = 0; i < 4; i++)
147
+            e->map[i] = rgba_map[e->map[i]];
148
+    }
149
+
141 150
     return 0;
142 151
 }
143 152
 
... ...
@@ -157,6 +178,31 @@ static int config_output(AVFilterLink *outlink)
157 157
     return 0;
158 158
 }
159 159
 
160
+static void extract_from_packed(uint8_t *dst, int dst_linesize,
161
+                                const uint8_t *src, int src_linesize,
162
+                                int width, int height,
163
+                                int depth, int step, int comp)
164
+{
165
+    int x, y;
166
+
167
+    for (y = 0; y < height; y++) {
168
+        switch (depth) {
169
+        case 1:
170
+            for (x = 0; x < width; x++)
171
+                dst[x] = src[x * step + comp];
172
+            break;
173
+        case 2:
174
+            for (x = 0; x < width; x++) {
175
+                dst[x * 2    ] = src[x * step + comp * 2    ];
176
+                dst[x * 2 + 1] = src[x * step + comp * 2 + 1];
177
+            }
178
+            break;
179
+        }
180
+        dst += dst_linesize;
181
+        src += src_linesize;
182
+    }
183
+}
184
+
160 185
 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
161 186
 {
162 187
     AVFilterContext *ctx = inlink->dst;
... ...
@@ -168,7 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
168 168
         const int idx = e->map[i];
169 169
         AVFrame *out;
170 170
 
171
-        if (outlink->closed || !frame->data[idx])
171
+        if (outlink->closed)
172 172
             continue;
173 173
 
174 174
         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
... ...
@@ -178,9 +224,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
178 178
         }
179 179
         av_frame_copy_props(out, frame);
180 180
 
181
-        av_image_copy_plane(out->data[0], out->linesize[0],
182
-                            frame->data[idx], frame->linesize[idx],
183
-                            e->linesize[idx], outlink->h);
181
+        if (e->is_packed_rgb) {
182
+            extract_from_packed(out->data[0], out->linesize[0],
183
+                                frame->data[0], frame->linesize[0],
184
+                                outlink->w, outlink->h,
185
+                                e->depth,
186
+                                e->step, idx);
187
+        } else {
188
+            av_image_copy_plane(out->data[0], out->linesize[0],
189
+                                frame->data[idx], frame->linesize[idx],
190
+                                e->linesize[idx], outlink->h);
191
+        }
192
+
184 193
         ret = ff_filter_frame(outlink, out);
185 194
         if (ret == AVERROR_EOF)
186 195
             eof++;