00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include <string.h>
00027
00028 #include "libavutil/pixfmt.h"
00029 #include "avfilter.h"
00030 #include "drawutils.h"
00031 #include "formats.h"
00032 #include "video.h"
00033
00034 enum { Y, U, V, A };
00035
00036 typedef struct {
00037 int is_packed_rgb;
00038 uint8_t rgba_map[4];
00039 } AlphaExtractContext;
00040
00041 static int query_formats(AVFilterContext *ctx)
00042 {
00043 enum PixelFormat in_fmts[] = {
00044 PIX_FMT_YUVA444P, PIX_FMT_YUVA422P, PIX_FMT_YUVA420P,
00045 PIX_FMT_RGBA, PIX_FMT_BGRA, PIX_FMT_ARGB, PIX_FMT_ABGR,
00046 PIX_FMT_NONE
00047 };
00048 enum PixelFormat out_fmts[] = { PIX_FMT_GRAY8, PIX_FMT_NONE };
00049 ff_formats_ref(ff_make_format_list(in_fmts), &ctx->inputs[0]->out_formats);
00050 ff_formats_ref(ff_make_format_list(out_fmts), &ctx->outputs[0]->in_formats);
00051 return 0;
00052 }
00053
00054 static int config_input(AVFilterLink *inlink)
00055 {
00056 AlphaExtractContext *extract = inlink->dst->priv;
00057 extract->is_packed_rgb =
00058 ff_fill_rgba_map(extract->rgba_map, inlink->format) >= 0;
00059 return 0;
00060 }
00061
00062 static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir)
00063 {
00064 AlphaExtractContext *extract = inlink->dst->priv;
00065 AVFilterBufferRef *cur_buf = inlink->cur_buf;
00066 AVFilterBufferRef *out_buf = inlink->dst->outputs[0]->out_buf;
00067
00068 if (extract->is_packed_rgb) {
00069 int x, y;
00070 uint8_t *pin, *pout;
00071 for (y = y0; y < (y0 + h); y++) {
00072 pin = cur_buf->data[0] + y * cur_buf->linesize[0] + extract->rgba_map[A];
00073 pout = out_buf->data[0] + y * out_buf->linesize[0];
00074 for (x = 0; x < out_buf->video->w; x++) {
00075 *pout = *pin;
00076 pout += 1;
00077 pin += 4;
00078 }
00079 }
00080 } else if (cur_buf->linesize[A] == out_buf->linesize[Y]) {
00081 const int linesize = cur_buf->linesize[A];
00082 memcpy(out_buf->data[Y] + y0 * linesize,
00083 cur_buf->data[A] + y0 * linesize,
00084 linesize * h);
00085 } else {
00086 const int linesize = FFMIN(out_buf->linesize[Y], cur_buf->linesize[A]);
00087 int y;
00088 for (y = y0; y < (y0 + h); y++) {
00089 memcpy(out_buf->data[Y] + y * out_buf->linesize[Y],
00090 cur_buf->data[A] + y * cur_buf->linesize[A],
00091 linesize);
00092 }
00093 }
00094 return ff_draw_slice(inlink->dst->outputs[0], y0, h, slice_dir);
00095 }
00096
00097 AVFilter avfilter_vf_alphaextract = {
00098 .name = "alphaextract",
00099 .description = NULL_IF_CONFIG_SMALL("Extract an alpha channel as a "
00100 "grayscale image component."),
00101 .priv_size = sizeof(AlphaExtractContext),
00102 .query_formats = query_formats,
00103
00104 .inputs = (const AVFilterPad[]) {
00105 { .name = "default",
00106 .type = AVMEDIA_TYPE_VIDEO,
00107 .config_props = config_input,
00108 .draw_slice = draw_slice,
00109 .min_perms = AV_PERM_READ },
00110 { .name = NULL }
00111 },
00112 .outputs = (const AVFilterPad[]) {
00113 { .name = "default",
00114 .type = AVMEDIA_TYPE_VIDEO, },
00115 { .name = NULL }
00116 },
00117 };