Unified · Split
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 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 { · 9 unmodified lines | ||
| 38 | 39 | int requested_planes; |
| 39 | 40 | int map[4]; |
| 40 | 41 | int linesize[4]; |
| 42 | + int is_packed_rgb; | |
| 43 | + int depth; | |
| 44 | + int step; | |
| 41 | 45 | } ExtractPlanesContext; |
| 42 | 46 | |
| 43 | 47 | #define OFFSET(x) offsetof(ExtractPlanesContext, x) |
| @@ -47,8 +51,8 @@ static const AVOption extractplanes_options[] = { · 3 unmodified lines | ||
| 47 | 51 | { "y", "set luma plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_Y}, 0, 0, FLAGS, "flags"}, |
| 48 | 52 | { "u", "set u plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_U}, 0, 0, FLAGS, "flags"}, |
| 49 | 53 | { "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 | 54 | { "r", "set red plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_R}, 0, 0, FLAGS, "flags"}, |
| 55 | + { "g", "set green plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_G}, 0, 0, FLAGS, "flags"}, | |
| 52 | 56 | { "b", "set blue plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_B}, 0, 0, FLAGS, "flags"}, |
| 53 | 57 | { "a", "set alpha plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_A}, 0, 0, FLAGS, "flags"}, |
| 54 | 58 | { NULL } |
| @@ -75,6 +79,13 @@ static int query_formats(AVFilterContext *ctx) · 20 unmodified lines | ||
| 75 | 79 | AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE, |
| 76 | 80 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, |
| 77 | 81 | AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, |
| 82 | + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, | |
| 83 | + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, | |
| 84 | + AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, | |
| 85 | + AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE, | |
| 86 | + AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE, | |
| 87 | + AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE, | |
| 88 | + AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE, | |
| 78 | 89 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
| 79 | 90 | AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE, |
| 80 | 91 | AV_PIX_FMT_GBRAP16LE, AV_PIX_FMT_GBRAP16BE, |
| @@ -125,7 +136,8 @@ static int config_input(AVFilterLink *inlink) · 44 unmodified lines | ||
| 125 | 136 | AVFilterContext *ctx = inlink->dst; |
| 126 | 137 | ExtractPlanesContext *e = ctx->priv; |
| 127 | 138 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
| 128 | − int plane_avail, ret; | |
| 139 | + int plane_avail, ret, i; | |
| 140 | + uint8_t rgba_map[4]; | |
| 129 | 141 | |
| 130 | 142 | plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B : |
| 131 | 143 | PLANE_Y | |
| @@ -138,6 +150,15 @@ static int config_input(AVFilterLink *inlink) · 6 unmodified lines | ||
| 138 | 150 | if ((ret = av_image_fill_linesizes(e->linesize, inlink->format, inlink->w)) < 0) |
| 139 | 151 | return ret; |
| 140 | 152 | |
| 153 | + e->depth = (desc->comp[0].depth_minus1 + 1) >> 3; | |
| 154 | + e->step = av_get_padded_bits_per_pixel(desc) >> 3; | |
| 155 | + e->is_packed_rgb = !(desc->flags & PIX_FMT_PLANAR); | |
| 156 | + if (desc->flags & PIX_FMT_RGB) { | |
| 157 | + ff_fill_rgba_map(rgba_map, inlink->format); | |
| 158 | + for (i = 0; i < 4; i++) | |
| 159 | + e->map[i] = rgba_map[e->map[i]]; | |
| 160 | + } | |
| 161 | + | |
| 141 | 162 | return 0; |
| 142 | 163 | } |
| 143 | 164 | |
| @@ -157,6 +178,31 @@ static int config_output(AVFilterLink *outlink) · 13 unmodified lines | ||
| 157 | 178 | return 0; |
| 158 | 179 | } |
| 159 | 180 | |
| 181 | +static void extract_from_packed(uint8_t *dst, int dst_linesize, | |
| 182 | + const uint8_t *src, int src_linesize, | |
| 183 | + int width, int height, | |
| 184 | + int depth, int step, int comp) | |
| 185 | +{ | |
| 186 | + int x, y; | |
| 187 | + | |
| 188 | + for (y = 0; y < height; y++) { | |
| 189 | + switch (depth) { | |
| 190 | + case 1: | |
| 191 | + for (x = 0; x < width; x++) | |
| 192 | + dst[x] = src[x * step + comp]; | |
| 193 | + break; | |
| 194 | + case 2: | |
| 195 | + for (x = 0; x < width; x++) { | |
| 196 | + dst[x * 2 ] = src[x * step + comp * 2 ]; | |
| 197 | + dst[x * 2 + 1] = src[x * step + comp * 2 + 1]; | |
| 198 | + } | |
| 199 | + break; | |
| 200 | + } | |
| 201 | + dst += dst_linesize; | |
| 202 | + src += src_linesize; | |
| 203 | + } | |
| 204 | +} | |
| 205 | + | |
| 160 | 206 | static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
| 161 | 207 | { |
| 162 | 208 | AVFilterContext *ctx = inlink->dst; |
| @@ -168,7 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 5 unmodified lines | ||
| 168 | 214 | const int idx = e->map[i]; |
| 169 | 215 | AVFrame *out; |
| 170 | 216 | |
| 171 | − if (outlink->closed || !frame->data[idx]) | |
| 217 | + if (outlink->closed) | |
| 172 | 218 | continue; |
| 173 | 219 | |
| 174 | 220 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
| @@ -178,9 +224,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 3 unmodified lines | ||
| 178 | 224 | } |
| 179 | 225 | av_frame_copy_props(out, frame); |
| 180 | 226 | |
| 181 | − av_image_copy_plane(out->data[0], out->linesize[0], | |
| 182 | − frame->data[idx], frame->linesize[idx], | |
| 183 | − e->linesize[idx], outlink->h); | |
| 227 | + if (e->is_packed_rgb) { | |
| 228 | + extract_from_packed(out->data[0], out->linesize[0], | |
| 229 | + frame->data[0], frame->linesize[0], | |
| 230 | + outlink->w, outlink->h, | |
| 231 | + e->depth, | |
| 232 | + e->step, idx); | |
| 233 | + } else { | |
| 234 | + av_image_copy_plane(out->data[0], out->linesize[0], | |
| 235 | + frame->data[idx], frame->linesize[idx], | |
| 236 | + e->linesize[idx], outlink->h); | |
| 237 | + } | |
| 238 | + | |
| 184 | 239 | ret = ff_filter_frame(outlink, out); |
| 185 | 240 | if (ret == AVERROR_EOF) |
| 186 | 241 | eof++; |