Unified · Split
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include "libavutil/opt.h" | 23 | #include "libavutil/opt.h" |
| 24 | #include "libavutil/pixdesc.h" | 24 | #include "libavutil/pixdesc.h" |
| 25 | #include "avfilter.h" | 25 | #include "avfilter.h" |
| 26 | #include "drawutils.h" | ||
| 26 | #include "internal.h" | 27 | #include "internal.h" |
| 27 | 28 | ||
| 28 | #define PLANE_R 0x01 | 29 | #define PLANE_R 0x01 |
| @@ -38,6 +39,9 @@ typedef struct { · 9 unmodified lines | |||
| 38 | int requested_planes; | 39 | int requested_planes; |
| 39 | int map[4]; | 40 | int map[4]; |
| 40 | int linesize[4]; | 41 | int linesize[4]; |
| 42 | int is_packed_rgb; | ||
| 43 | int depth; | ||
| 44 | int step; | ||
| 41 | } ExtractPlanesContext; | 45 | } ExtractPlanesContext; |
| 42 | 46 | ||
| 43 | #define OFFSET(x) offsetof(ExtractPlanesContext, x) | 47 | #define OFFSET(x) offsetof(ExtractPlanesContext, x) |
| @@ -47,8 +51,8 @@ static const AVOption extractplanes_options[] = { · 3 unmodified lines | |||
| 47 | { "y", "set luma plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_Y}, 0, 0, FLAGS, "flags"}, | 51 | { "y", "set luma plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_Y}, 0, 0, FLAGS, "flags"}, |
| 48 | { "u", "set u plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_U}, 0, 0, FLAGS, "flags"}, | 52 | { "u", "set u plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_U}, 0, 0, FLAGS, "flags"}, |
| 49 | { "v", "set v plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_V}, 0, 0, FLAGS, "flags"}, | 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 | { "r", "set red plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_R}, 0, 0, FLAGS, "flags"}, | 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 | { "b", "set blue plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_B}, 0, 0, FLAGS, "flags"}, | 56 | { "b", "set blue plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_B}, 0, 0, FLAGS, "flags"}, |
| 53 | { "a", "set alpha plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_A}, 0, 0, FLAGS, "flags"}, | 57 | { "a", "set alpha plane", 0, AV_OPT_TYPE_CONST, {.i64=PLANE_A}, 0, 0, FLAGS, "flags"}, |
| 54 | { NULL } | 58 | { NULL } |
| @@ -75,6 +79,13 @@ static int query_formats(AVFilterContext *ctx) · 20 unmodified lines | |||
| 75 | AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE, | 79 | AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE, |
| 76 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, | 80 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, |
| 77 | AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, | 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 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, | 89 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
| 79 | AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE, | 90 | AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE, |
| 80 | AV_PIX_FMT_GBRAP16LE, AV_PIX_FMT_GBRAP16BE, | 91 | AV_PIX_FMT_GBRAP16LE, AV_PIX_FMT_GBRAP16BE, |
| @@ -125,7 +136,8 @@ static int config_input(AVFilterLink *inlink) · 44 unmodified lines | |||
| 125 | AVFilterContext *ctx = inlink->dst; | 136 | AVFilterContext *ctx = inlink->dst; |
| 126 | ExtractPlanesContext *e = ctx->priv; | 137 | ExtractPlanesContext *e = ctx->priv; |
| 127 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | 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 | plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B : | 142 | plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B : |
| 131 | PLANE_Y | | 143 | PLANE_Y | |
| @@ -138,6 +150,15 @@ static int config_input(AVFilterLink *inlink) · 6 unmodified lines | |||
| 138 | if ((ret = av_image_fill_linesizes(e->linesize, inlink->format, inlink->w)) < 0) | 150 | if ((ret = av_image_fill_linesizes(e->linesize, inlink->format, inlink->w)) < 0) |
| 139 | return ret; | 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 | return 0; | 162 | return 0; |
| 142 | } | 163 | } |
| 143 | 164 | ||
| @@ -157,6 +178,31 @@ static int config_output(AVFilterLink *outlink) · 13 unmodified lines | |||
| 157 | return 0; | 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 | static int filter_frame(AVFilterLink *inlink, AVFrame *frame) | 206 | static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
| 161 | { | 207 | { |
| 162 | AVFilterContext *ctx = inlink->dst; | 208 | AVFilterContext *ctx = inlink->dst; |
| @@ -168,7 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 5 unmodified lines | |||
| 168 | const int idx = e->map[i]; | 214 | const int idx = e->map[i]; |
| 169 | AVFrame *out; | 215 | AVFrame *out; |
| 170 | 216 | ||
| 171 | if (outlink->closed || !frame->data[idx]) | 217 | if (outlink->closed) |
| 172 | continue; | 218 | continue; |
| 173 | 219 | ||
| 174 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | 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 | av_frame_copy_props(out, frame); | 225 | av_frame_copy_props(out, frame); |
| 180 | 226 | ||
| 181 | av_image_copy_plane(out->data[0], out->linesize[0], | 227 | if (e->is_packed_rgb) { |
| 182 | frame->data[idx], frame->linesize[idx], | 228 | extract_from_packed(out->data[0], out->linesize[0], |
| 183 | e->linesize[idx], outlink->h); | 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 | ret = ff_filter_frame(outlink, out); | 239 | ret = ff_filter_frame(outlink, out); |
| 185 | if (ret == AVERROR_EOF) | 240 | if (ret == AVERROR_EOF) |
| 186 | eof++; | 241 | eof++; |