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 "internal.h"
00032 #include "formats.h"
00033 #include "video.h"
00034
00035 enum { Y, U, V, A };
00036
00037 typedef struct {
00038 int is_packed_rgb;
00039 uint8_t rgba_map[4];
00040 } AlphaExtractContext;
00041
00042 static int query_formats(AVFilterContext *ctx)
00043 {
00044 enum AVPixelFormat in_fmts[] = {
00045 AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
00046 AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
00047 AV_PIX_FMT_NONE
00048 };
00049 enum AVPixelFormat out_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
00050 ff_formats_ref(ff_make_format_list(in_fmts), &ctx->inputs[0]->out_formats);
00051 ff_formats_ref(ff_make_format_list(out_fmts), &ctx->outputs[0]->in_formats);
00052 return 0;
00053 }
00054
00055 static int config_input(AVFilterLink *inlink)
00056 {
00057 AlphaExtractContext *extract = inlink->dst->priv;
00058 extract->is_packed_rgb =
00059 ff_fill_rgba_map(extract->rgba_map, inlink->format) >= 0;
00060 return 0;
00061 }
00062
00063 static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *cur_buf)
00064 {
00065 AlphaExtractContext *extract = inlink->dst->priv;
00066 AVFilterLink *outlink = inlink->dst->outputs[0];
00067 AVFilterBufferRef *out_buf =
00068 ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
00069 int ret;
00070
00071 if (!out_buf) {
00072 ret = AVERROR(ENOMEM);
00073 goto end;
00074 }
00075 avfilter_copy_buffer_ref_props(out_buf, cur_buf);
00076
00077 if (extract->is_packed_rgb) {
00078 int x, y;
00079 uint8_t *pcur, *pout;
00080 for (y = 0; y < outlink->h; y++) {
00081 pcur = cur_buf->data[0] + y * cur_buf->linesize[0] + extract->rgba_map[A];
00082 pout = out_buf->data[0] + y * out_buf->linesize[0];
00083 for (x = 0; x < outlink->w; x++) {
00084 *pout = *pcur;
00085 pout += 1;
00086 pcur += 4;
00087 }
00088 }
00089 } else {
00090 const int linesize = abs(FFMIN(out_buf->linesize[Y], cur_buf->linesize[A]));
00091 int y;
00092 for (y = 0; y < outlink->h; y++) {
00093 memcpy(out_buf->data[Y] + y * out_buf->linesize[Y],
00094 cur_buf->data[A] + y * cur_buf->linesize[A],
00095 linesize);
00096 }
00097 }
00098
00099 ret = ff_filter_frame(outlink, out_buf);
00100
00101 end:
00102 avfilter_unref_buffer(cur_buf);
00103 return ret;
00104 }
00105
00106 static const AVFilterPad alphaextract_inputs[] = {
00107 {
00108 .name = "default",
00109 .type = AVMEDIA_TYPE_VIDEO,
00110 .config_props = config_input,
00111 .filter_frame = filter_frame,
00112 .min_perms = AV_PERM_READ,
00113 },
00114 { NULL }
00115 };
00116
00117 static const AVFilterPad alphaextract_outputs[] = {
00118 {
00119 .name = "default",
00120 .type = AVMEDIA_TYPE_VIDEO,
00121 },
00122 { NULL }
00123 };
00124
00125 AVFilter avfilter_vf_alphaextract = {
00126 .name = "alphaextract",
00127 .description = NULL_IF_CONFIG_SMALL("Extract an alpha channel as a "
00128 "grayscale image component."),
00129 .priv_size = sizeof(AlphaExtractContext),
00130 .query_formats = query_formats,
00131 .inputs = alphaextract_inputs,
00132 .outputs = alphaextract_outputs,
00133 };