History

vf_overlay: enable RGB path

Add option rgb which forces the RGB path.

Stefano Sabatini committed 15 years ago

Commit 3013bfa1 parent c0dbab92 files · +116 −20Browse files

Unified · Split

2 files
  1. doc/filters.texi +13 −2
  2. libavfilter/vf_overlay.c +103 −18
doc/filters.texi+13−2
@@ -1631,10 +1631,10 @@ Overlay one video on top of another. · 1630 unmodified lines
1631It takes two inputs and one output, the first input is the "main"1631It takes two inputs and one output, the first input is the "main"
1632video on which the second input is overlayed.1632video on which the second input is overlayed.
1633 1633
1634It accepts the parameters: @var{x}:@var{y}.1634It accepts the parameters: @var{x}:@var{y}[:@var{options}].
1635 1635
1636@var{x} is the x coordinate of the overlayed video on the main video,1636@var{x} is the x coordinate of the overlayed video on the main video,
1637@var{y} is the y coordinate. The parameters are expressions containing1637@var{y} is the y coordinate. @var{x} and @var{y} are expressions containing
1638the following parameters:1638the following parameters:
1639 1639
1640@table @option1640@table @option
@@ -1651,6 +1651,17 @@ overlay input width and height · 10 unmodified lines
1651same as @var{overlay_w} and @var{overlay_h}1651same as @var{overlay_w} and @var{overlay_h}
1652@end table1652@end table
1653 1653
1654@var{options} is an optional list of @var{key}=@var{value} pairs,
1655separated by ":".
1656
1657The description of the accepted options follows.
1658
1659@table @option
1660@item rgb
1661If set to 1, force the filter to accept inputs in the RGB
1662colorspace. Default value is 0.
1663@end table
1664
1654Be aware that frames are taken from each input video in timestamp1665Be aware that frames are taken from each input video in timestamp
1655order, hence, if their initial timestamps differ, it is a a good idea1666order, hence, if their initial timestamps differ, it is a a good idea
1656to pass the two inputs through a @var{setpts=PTS-STARTPTS} filter to1667to pass the two inputs through a @var{setpts=PTS-STARTPTS} filter to
libavfilter/vf_overlay.c+103−18
@@ -33,6 +33,7 @@ · 32 unmodified lines
33#include "libavutil/imgutils.h"33#include "libavutil/imgutils.h"
34#include "libavutil/mathematics.h"34#include "libavutil/mathematics.h"
35#include "internal.h"35#include "internal.h"
36#include "drawutils.h"
36 37
37static const char *var_names[] = {38static const char *var_names[] = {
38 "main_w", "W", ///< width of the main video39 "main_w", "W", ///< width of the main video
@@ -53,13 +54,31 @@ enum var_name { · 14 unmodified lines
53#define MAIN 054#define MAIN 0
54#define OVERLAY 155#define OVERLAY 1
55 56
57#define R 0
58#define G 1
59#define B 2
60#define A 3
61
62#define Y 0
63#define U 1
64#define V 2
65
56typedef struct {66typedef struct {
57 const AVClass *class;67 const AVClass *class;
58 int x, y; ///< position of overlayed picture68 int x, y; ///< position of overlayed picture
59 69
70 int allow_packed_rgb;
71 uint8_t main_is_packed_rgb;
72 uint8_t main_rgba_map[4];
73 uint8_t main_has_alpha;
74 uint8_t overlay_is_packed_rgb;
75 uint8_t overlay_rgba_map[4];
76 uint8_t overlay_has_alpha;
77
60 AVFilterBufferRef *overpicref;78 AVFilterBufferRef *overpicref;
61 79
62 int max_plane_step[4]; ///< steps per pixel for each plane80 int main_pix_step[4]; ///< steps per pixel for each plane of the main output
81 int overlay_pix_step[4]; ///< steps per pixel for each plane of the overlay
63 int hsub, vsub; ///< chroma subsampling values82 int hsub, vsub; ///< chroma subsampling values
64 83
65 char *x_expr, *y_expr;84 char *x_expr, *y_expr;
@@ -70,6 +89,7 @@ typedef struct { · 4 unmodified lines
70static const AVOption overlay_options[] = {89static const AVOption overlay_options[] = {
71 { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX },90 { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX },
72 { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX },91 { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX },
92 {"rgb", "force packed RGB in input and output", OFFSET(allow_packed_rgb), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
73 {NULL},93 {NULL},
74};94};
75 95
@@ -128,27 +148,59 @@ static av_cold void uninit(AVFilterContext *ctx) · 52 unmodified lines
128 148
129static int query_formats(AVFilterContext *ctx)149static int query_formats(AVFilterContext *ctx)
130{150{
131 const enum PixelFormat inout_pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };151 OverlayContext *over = ctx->priv;
132 const enum PixelFormat blend_pix_fmts[] = { PIX_FMT_YUVA420P, PIX_FMT_NONE };
133 AVFilterFormats *inout_formats = avfilter_make_format_list(inout_pix_fmts);
134 AVFilterFormats *blend_formats = avfilter_make_format_list(blend_pix_fmts);
135 152
136 avfilter_formats_ref(inout_formats, &ctx->inputs [MAIN ]->out_formats);153 /* overlay formats contains alpha, for avoiding conversion with alpha information loss */
137 avfilter_formats_ref(blend_formats, &ctx->inputs [OVERLAY]->out_formats);154 const enum PixelFormat main_pix_fmts_yuv[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
138 avfilter_formats_ref(inout_formats, &ctx->outputs[MAIN ]->in_formats );155 const enum PixelFormat overlay_pix_fmts_yuv[] = { PIX_FMT_YUVA420P, PIX_FMT_NONE };
156 const enum PixelFormat main_pix_fmts_rgb[] = {
157 PIX_FMT_ARGB, PIX_FMT_RGBA,
158 PIX_FMT_ABGR, PIX_FMT_BGRA,
159 PIX_FMT_RGB24, PIX_FMT_BGR24,
160 PIX_FMT_NONE
161 };
162 const enum PixelFormat overlay_pix_fmts_rgb[] = {
163 PIX_FMT_ARGB, PIX_FMT_RGBA,
164 PIX_FMT_ABGR, PIX_FMT_BGRA,
165 PIX_FMT_NONE
166 };
167
168 AVFilterFormats *main_formats;
169 AVFilterFormats *overlay_formats;
170
171 if (over->allow_packed_rgb) {
172 main_formats = avfilter_make_format_list(main_pix_fmts_rgb);
173 overlay_formats = avfilter_make_format_list(overlay_pix_fmts_rgb);
174 } else {
175 main_formats = avfilter_make_format_list(main_pix_fmts_yuv);
176 overlay_formats = avfilter_make_format_list(overlay_pix_fmts_yuv);
177 }
178
179 avfilter_formats_ref(main_formats, &ctx->inputs [MAIN ]->out_formats);
180 avfilter_formats_ref(overlay_formats, &ctx->inputs [OVERLAY]->out_formats);
181 avfilter_formats_ref(main_formats, &ctx->outputs[MAIN ]->in_formats );
139 182
140 return 0;183 return 0;
141}184}
142 185
186static enum PixelFormat alpha_pix_fmts[] = {
187 PIX_FMT_YUVA420P, PIX_FMT_ARGB, PIX_FMT_ABGR, PIX_FMT_RGBA,
188 PIX_FMT_BGRA, PIX_FMT_NONE
189};
190
143static int config_input_main(AVFilterLink *inlink)191static int config_input_main(AVFilterLink *inlink)
144{192{
145 OverlayContext *over = inlink->dst->priv;193 OverlayContext *over = inlink->dst->priv;
146 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];194 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
147 195
148 av_image_fill_max_pixsteps(over->max_plane_step, NULL, pix_desc);196 av_image_fill_max_pixsteps(over->main_pix_step, NULL, pix_desc);
197
149 over->hsub = pix_desc->log2_chroma_w;198 over->hsub = pix_desc->log2_chroma_w;
150 over->vsub = pix_desc->log2_chroma_h;199 over->vsub = pix_desc->log2_chroma_h;
151 200
201 over->main_is_packed_rgb =
202 ff_fill_rgba_map(over->main_rgba_map, inlink->format) >= 0;
203 over->main_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
152 return 0;204 return 0;
153}205}
154 206
@@ -159,6 +211,9 @@ static int config_input_overlay(AVFilterLink *inlink) · 4 unmodified lines
159 char *expr;211 char *expr;
160 double var_values[VAR_VARS_NB], res;212 double var_values[VAR_VARS_NB], res;
161 int ret;213 int ret;
214 const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
215
216 av_image_fill_max_pixsteps(over->overlay_pix_step, NULL, pix_desc);
162 217
163 /* Finish the configuration by evaluating the expressions218 /* Finish the configuration by evaluating the expressions
164 now when both inputs are configured. */219 now when both inputs are configured. */
@@ -181,6 +236,10 @@ static int config_input_overlay(AVFilterLink *inlink) · 16 unmodified lines
181 goto fail;236 goto fail;
182 over->x = res;237 over->x = res;
183 238
239 over->overlay_is_packed_rgb =
240 ff_fill_rgba_map(over->overlay_rgba_map, inlink->format) >= 0;
241 over->overlay_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
242
184 av_log(ctx, AV_LOG_INFO,243 av_log(ctx, AV_LOG_INFO,
185 "main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s\n",244 "main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s\n",
186 ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,245 ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,
@@ -272,6 +331,10 @@ static void start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicre · 85 unmodified lines
272 ctx->outputs[0]->time_base);331 ctx->outputs[0]->time_base);
273}332}
274 333
334// divide by 255 and round to nearest
335// apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
336#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
337
275static void blend_slice(AVFilterContext *ctx,338static void blend_slice(AVFilterContext *ctx,
276 AVFilterBufferRef *dst, AVFilterBufferRef *src,339 AVFilterBufferRef *dst, AVFilterBufferRef *src,
277 int x, int y, int w, int h,340 int x, int y, int w, int h,
@@ -289,21 +352,43 @@ static void blend_slice(AVFilterContext *ctx, · 11 unmodified lines
289 start_y = FFMAX(y, slice_y);352 start_y = FFMAX(y, slice_y);
290 height = end_y - start_y;353 height = end_y - start_y;
291 354
292 if (dst->format == PIX_FMT_BGR24 || dst->format == PIX_FMT_RGB24) {355 if (over->main_is_packed_rgb) {
293 uint8_t *dp = dst->data[0] + x * 3 + start_y * dst->linesize[0];356 uint8_t *dp = dst->data[0] + x * over->main_pix_step[0] +
357 start_y * dst->linesize[0];
294 uint8_t *sp = src->data[0];358 uint8_t *sp = src->data[0];
295 int b = dst->format == PIX_FMT_BGR24 ? 2 : 0;359 uint8_t alpha; ///< the amount of overlay to blend on to main
296 int r = dst->format == PIX_FMT_BGR24 ? 0 : 2;360 const int dr = over->main_rgba_map[R];
361 const int dg = over->main_rgba_map[G];
362 const int db = over->main_rgba_map[B];
363 const int dstep = over->main_pix_step[0];
364 const int sr = over->overlay_rgba_map[R];
365 const int sg = over->overlay_rgba_map[G];
366 const int sb = over->overlay_rgba_map[B];
367 const int sa = over->overlay_rgba_map[A];
368 const int sstep = over->overlay_pix_step[0];
297 if (slice_y > y)369 if (slice_y > y)
298 sp += (slice_y - y) * src->linesize[0];370 sp += (slice_y - y) * src->linesize[0];
299 for (i = 0; i < height; i++) {371 for (i = 0; i < height; i++) {
300 uint8_t *d = dp, *s = sp;372 uint8_t *d = dp, *s = sp;
301 for (j = 0; j < width; j++) {373 for (j = 0; j < width; j++) {
302 d[r] = (d[r] * (0xff - s[3]) + s[0] * s[3] + 128) >> 8;374 alpha = s[sa];
303 d[1] = (d[1] * (0xff - s[3]) + s[1] * s[3] + 128) >> 8;375 switch (alpha) {
304 d[b] = (d[b] * (0xff - s[3]) + s[2] * s[3] + 128) >> 8;376 case 0:
305 d += 3;377 break;
306 s += 4;378 case 255:
379 d[dr] = s[sr];
380 d[dg] = s[sg];
381 d[db] = s[sb];
382 break;
383 default:
384 // main_value = main_value * (1 - alpha) + overlay_value * alpha
385 // since alpha is in the range 0-255, the result must divided by 255
386 d[dr] = FAST_DIV255(d[dr] * (255 - alpha) + s[sr] * alpha);
387 d[dg] = FAST_DIV255(d[dg] * (255 - alpha) + s[sg] * alpha);
388 d[db] = FAST_DIV255(d[db] * (255 - alpha) + s[sb] * alpha);
389 }
390 d += dstep;
391 s += sstep;
307 }392 }
308 dp += dst->linesize[0];393 dp += dst->linesize[0];
309 sp += src->linesize[0];394 sp += src->linesize[0];

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t