2 * Copyright (c) 2008 Affine Systems, Inc (Michael Sullivan, Bobby Impollonia)
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Box drawing filter. Also a nice template for a filter that needs to
24 * write in the input frame.
27 #include "libavutil/colorspace.h"
28 #include "libavutil/common.h"
29 #include "libavutil/pixdesc.h"
30 #include "libavutil/parseutils.h"
40 unsigned char yuv_color
[4];
41 int vsub
, hsub
; ///< chroma subsampling
44 static av_cold
int init(AVFilterContext
*ctx
, const char *args
)
46 DrawBoxContext
*drawbox
= ctx
->priv
;
47 char color_str
[1024] = "black";
48 uint8_t rgba_color
[4];
50 drawbox
->x
= drawbox
->y
= drawbox
->w
= drawbox
->h
= 0;
53 sscanf(args
, "%d:%d:%d:%d:%s",
54 &drawbox
->x
, &drawbox
->y
, &drawbox
->w
, &drawbox
->h
, color_str
);
56 if (av_parse_color(rgba_color
, color_str
, -1, ctx
) < 0)
57 return AVERROR(EINVAL
);
59 drawbox
->yuv_color
[Y
] = RGB_TO_Y_CCIR(rgba_color
[0], rgba_color
[1], rgba_color
[2]);
60 drawbox
->yuv_color
[U
] = RGB_TO_U_CCIR(rgba_color
[0], rgba_color
[1], rgba_color
[2], 0);
61 drawbox
->yuv_color
[V
] = RGB_TO_V_CCIR(rgba_color
[0], rgba_color
[1], rgba_color
[2], 0);
62 drawbox
->yuv_color
[A
] = rgba_color
[3];
67 static int query_formats(AVFilterContext
*ctx
)
69 enum AVPixelFormat pix_fmts
[] = {
70 AV_PIX_FMT_YUV444P
, AV_PIX_FMT_YUV422P
, AV_PIX_FMT_YUV420P
,
71 AV_PIX_FMT_YUV411P
, AV_PIX_FMT_YUV410P
,
72 AV_PIX_FMT_YUVJ444P
, AV_PIX_FMT_YUVJ422P
, AV_PIX_FMT_YUVJ420P
,
73 AV_PIX_FMT_YUV440P
, AV_PIX_FMT_YUVJ440P
,
77 ff_set_common_formats(ctx
, ff_make_format_list(pix_fmts
));
81 static int config_input(AVFilterLink
*inlink
)
83 DrawBoxContext
*drawbox
= inlink
->dst
->priv
;
84 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(inlink
->format
);
86 drawbox
->hsub
= desc
->log2_chroma_w
;
87 drawbox
->vsub
= desc
->log2_chroma_h
;
89 if (drawbox
->w
== 0) drawbox
->w
= inlink
->w
;
90 if (drawbox
->h
== 0) drawbox
->h
= inlink
->h
;
92 av_log(inlink
->dst
, AV_LOG_VERBOSE
, "x:%d y:%d w:%d h:%d color:0x%02X%02X%02X%02X\n",
93 drawbox
->w
, drawbox
->y
, drawbox
->w
, drawbox
->h
,
94 drawbox
->yuv_color
[Y
], drawbox
->yuv_color
[U
], drawbox
->yuv_color
[V
], drawbox
->yuv_color
[A
]);
99 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*frame
)
101 DrawBoxContext
*drawbox
= inlink
->dst
->priv
;
102 int plane
, x
, y
, xb
= drawbox
->x
, yb
= drawbox
->y
;
103 unsigned char *row
[4];
105 for (y
= FFMAX(yb
, 0); y
< frame
->height
&& y
< (yb
+ drawbox
->h
); y
++) {
106 row
[0] = frame
->data
[0] + y
* frame
->linesize
[0];
108 for (plane
= 1; plane
< 3; plane
++)
109 row
[plane
] = frame
->data
[plane
] +
110 frame
->linesize
[plane
] * (y
>> drawbox
->vsub
);
112 for (x
= FFMAX(xb
, 0); x
< (xb
+ drawbox
->w
) && x
< frame
->width
; x
++) {
113 double alpha
= (double)drawbox
->yuv_color
[A
] / 255;
115 if ((y
- yb
< 3) || (yb
+ drawbox
->h
- y
< 4) ||
116 (x
- xb
< 3) || (xb
+ drawbox
->w
- x
< 4)) {
117 row
[0][x
] = (1 - alpha
) * row
[0][x
] + alpha
* drawbox
->yuv_color
[Y
];
118 row
[1][x
>> drawbox
->hsub
] = (1 - alpha
) * row
[1][x
>> drawbox
->hsub
] + alpha
* drawbox
->yuv_color
[U
];
119 row
[2][x
>> drawbox
->hsub
] = (1 - alpha
) * row
[2][x
>> drawbox
->hsub
] + alpha
* drawbox
->yuv_color
[V
];
124 return ff_filter_frame(inlink
->dst
->outputs
[0], frame
);
127 static const AVFilterPad avfilter_vf_drawbox_inputs
[] = {
130 .type
= AVMEDIA_TYPE_VIDEO
,
131 .config_props
= config_input
,
132 .get_video_buffer
= ff_null_get_video_buffer
,
133 .filter_frame
= filter_frame
,
139 static const AVFilterPad avfilter_vf_drawbox_outputs
[] = {
142 .type
= AVMEDIA_TYPE_VIDEO
,
147 AVFilter avfilter_vf_drawbox
= {
149 .description
= NULL_IF_CONFIG_SMALL("Draw a colored box on the input video."),
150 .priv_size
= sizeof(DrawBoxContext
),
153 .query_formats
= query_formats
,
154 .inputs
= avfilter_vf_drawbox_inputs
,
155 .outputs
= avfilter_vf_drawbox_outputs
,