mp3: Properly use AVCodecContext API
[platform/upstream/libav.git] / libavfilter / vf_overlay.c
1 /*
2  * Copyright (c) 2010 Stefano Sabatini
3  * Copyright (c) 2010 Baptiste Coudurier
4  * Copyright (c) 2007 Bobby Bingham
5  *
6  * This file is part of Libav.
7  *
8  * Libav is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * Libav is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file
25  * overlay one video on top of another
26  */
27
28 #include "avfilter.h"
29 #include "formats.h"
30 #include "libavutil/common.h"
31 #include "libavutil/eval.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/avassert.h"
34 #include "libavutil/pixdesc.h"
35 #include "libavutil/imgutils.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/opt.h"
38 #include "internal.h"
39 #include "video.h"
40
41 static const char *const var_names[] = {
42     "E",
43     "PHI",
44     "PI",
45     "main_w",    "W", ///< width  of the main    video
46     "main_h",    "H", ///< height of the main    video
47     "overlay_w", "w", ///< width  of the overlay video
48     "overlay_h", "h", ///< height of the overlay video
49     NULL
50 };
51
52 enum var_name {
53     VAR_E,
54     VAR_PHI,
55     VAR_PI,
56     VAR_MAIN_W,    VAR_MW,
57     VAR_MAIN_H,    VAR_MH,
58     VAR_OVERLAY_W, VAR_OW,
59     VAR_OVERLAY_H, VAR_OH,
60     VAR_VARS_NB
61 };
62
63 enum EOFAction {
64     EOF_ACTION_REPEAT,
65     EOF_ACTION_ENDALL,
66     EOF_ACTION_PASS
67 };
68
69 static const char *eof_action_str[] = {
70     "repeat", "endall", "pass"
71 };
72
73 #define MAIN    0
74 #define OVERLAY 1
75
76 typedef struct OverlayContext {
77     const AVClass *class;
78     int x, y;                   ///< position of overlayed picture
79
80     int max_plane_step[4];      ///< steps per pixel for each plane
81     int hsub, vsub;             ///< chroma subsampling values
82
83     char *x_expr, *y_expr;
84
85     enum EOFAction eof_action;  ///< action to take on EOF from source
86
87     AVFrame *main;
88     AVFrame *over_prev, *over_next;
89 } OverlayContext;
90
91 static av_cold void uninit(AVFilterContext *ctx)
92 {
93     OverlayContext *s = ctx->priv;
94
95     av_frame_free(&s->main);
96     av_frame_free(&s->over_prev);
97     av_frame_free(&s->over_next);
98 }
99
100 static int query_formats(AVFilterContext *ctx)
101 {
102     const enum AVPixelFormat inout_pix_fmts[] = { AV_PIX_FMT_YUV420P,  AV_PIX_FMT_NONE };
103     const enum AVPixelFormat blend_pix_fmts[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE };
104     AVFilterFormats *inout_formats = ff_make_format_list(inout_pix_fmts);
105     AVFilterFormats *blend_formats = ff_make_format_list(blend_pix_fmts);
106
107     ff_formats_ref(inout_formats, &ctx->inputs [MAIN   ]->out_formats);
108     ff_formats_ref(blend_formats, &ctx->inputs [OVERLAY]->out_formats);
109     ff_formats_ref(inout_formats, &ctx->outputs[MAIN   ]->in_formats );
110
111     return 0;
112 }
113
114 static int config_input_main(AVFilterLink *inlink)
115 {
116     OverlayContext *s = inlink->dst->priv;
117     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
118
119     av_image_fill_max_pixsteps(s->max_plane_step, NULL, pix_desc);
120     s->hsub = pix_desc->log2_chroma_w;
121     s->vsub = pix_desc->log2_chroma_h;
122
123     return 0;
124 }
125
126 static int config_input_overlay(AVFilterLink *inlink)
127 {
128     AVFilterContext *ctx  = inlink->dst;
129     OverlayContext  *s = inlink->dst->priv;
130     char *expr;
131     double var_values[VAR_VARS_NB], res;
132     int ret;
133
134     /* Finish the configuration by evaluating the expressions
135        now when both inputs are configured. */
136     var_values[VAR_E  ] = M_E;
137     var_values[VAR_PHI] = M_PHI;
138     var_values[VAR_PI ] = M_PI;
139
140     var_values[VAR_MAIN_W   ] = var_values[VAR_MW] = ctx->inputs[MAIN   ]->w;
141     var_values[VAR_MAIN_H   ] = var_values[VAR_MH] = ctx->inputs[MAIN   ]->h;
142     var_values[VAR_OVERLAY_W] = var_values[VAR_OW] = ctx->inputs[OVERLAY]->w;
143     var_values[VAR_OVERLAY_H] = var_values[VAR_OH] = ctx->inputs[OVERLAY]->h;
144
145     if ((ret = av_expr_parse_and_eval(&res, (expr = s->x_expr), var_names, var_values,
146                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
147         goto fail;
148     s->x = res;
149     if ((ret = av_expr_parse_and_eval(&res, (expr = s->y_expr), var_names, var_values,
150                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)))
151         goto fail;
152     s->y = res;
153     /* x may depend on y */
154     if ((ret = av_expr_parse_and_eval(&res, (expr = s->x_expr), var_names, var_values,
155                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
156         goto fail;
157     s->x = res;
158
159     av_log(ctx, AV_LOG_VERBOSE,
160            "main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s eof_action:%s\n",
161            ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,
162            av_get_pix_fmt_name(ctx->inputs[MAIN]->format),
163            s->x, s->y,
164            ctx->inputs[OVERLAY]->w, ctx->inputs[OVERLAY]->h,
165            av_get_pix_fmt_name(ctx->inputs[OVERLAY]->format),
166            eof_action_str[s->eof_action]);
167
168     if (s->x < 0 || s->y < 0 ||
169         s->x + var_values[VAR_OVERLAY_W] > var_values[VAR_MAIN_W] ||
170         s->y + var_values[VAR_OVERLAY_H] > var_values[VAR_MAIN_H]) {
171         av_log(ctx, AV_LOG_ERROR,
172                "Overlay area (%d,%d)<->(%d,%d) not within the main area (0,0)<->(%d,%d) or zero-sized\n",
173                s->x, s->y,
174                (int)(s->x + var_values[VAR_OVERLAY_W]),
175                (int)(s->y + var_values[VAR_OVERLAY_H]),
176                (int)var_values[VAR_MAIN_W], (int)var_values[VAR_MAIN_H]);
177         return AVERROR(EINVAL);
178     }
179     return 0;
180
181 fail:
182     av_log(NULL, AV_LOG_ERROR,
183            "Error when evaluating the expression '%s'\n", expr);
184     return ret;
185 }
186
187 static int config_output(AVFilterLink *outlink)
188 {
189     AVFilterContext *ctx = outlink->src;
190
191     outlink->w = ctx->inputs[MAIN]->w;
192     outlink->h = ctx->inputs[MAIN]->h;
193     outlink->time_base = ctx->inputs[MAIN]->time_base;
194
195     return 0;
196 }
197
198 static void blend_frame(AVFilterContext *ctx,
199                         AVFrame *dst, AVFrame *src,
200                         int x, int y)
201 {
202     OverlayContext *s = ctx->priv;
203     int i, j, k;
204     int width, height;
205     int overlay_end_y = y + src->height;
206     int end_y, start_y;
207
208     width = FFMIN(dst->width - x, src->width);
209     end_y = FFMIN(dst->height, overlay_end_y);
210     start_y = FFMAX(y, 0);
211     height = end_y - start_y;
212
213     if (dst->format == AV_PIX_FMT_BGR24 || dst->format == AV_PIX_FMT_RGB24) {
214         uint8_t *dp = dst->data[0] + x * 3 + start_y * dst->linesize[0];
215         uint8_t *sp = src->data[0];
216         int b = dst->format == AV_PIX_FMT_BGR24 ? 2 : 0;
217         int r = dst->format == AV_PIX_FMT_BGR24 ? 0 : 2;
218         if (y < 0)
219             sp += -y * src->linesize[0];
220         for (i = 0; i < height; i++) {
221             uint8_t *d = dp, *s = sp;
222             for (j = 0; j < width; j++) {
223                 d[r] = (d[r] * (0xff - s[3]) + s[0] * s[3] + 128) >> 8;
224                 d[1] = (d[1] * (0xff - s[3]) + s[1] * s[3] + 128) >> 8;
225                 d[b] = (d[b] * (0xff - s[3]) + s[2] * s[3] + 128) >> 8;
226                 d += 3;
227                 s += 4;
228             }
229             dp += dst->linesize[0];
230             sp += src->linesize[0];
231         }
232     } else {
233         for (i = 0; i < 3; i++) {
234             int hsub = i ? s->hsub : 0;
235             int vsub = i ? s->vsub : 0;
236             uint8_t *dp = dst->data[i] + (x >> hsub) +
237                 (start_y >> vsub) * dst->linesize[i];
238             uint8_t *sp = src->data[i];
239             uint8_t *ap = src->data[3];
240             int wp = FFALIGN(width, 1<<hsub) >> hsub;
241             int hp = FFALIGN(height, 1<<vsub) >> vsub;
242             if (y < 0) {
243                 sp += ((-y) >> vsub) * src->linesize[i];
244                 ap += -y * src->linesize[3];
245             }
246             for (j = 0; j < hp; j++) {
247                 uint8_t *d = dp, *s = sp, *a = ap;
248                 for (k = 0; k < wp; k++) {
249                     // average alpha for color components, improve quality
250                     int alpha_v, alpha_h, alpha;
251                     if (hsub && vsub && j+1 < hp && k+1 < wp) {
252                         alpha = (a[0] + a[src->linesize[3]] +
253                                  a[1] + a[src->linesize[3]+1]) >> 2;
254                     } else if (hsub || vsub) {
255                         alpha_h = hsub && k+1 < wp ?
256                             (a[0] + a[1]) >> 1 : a[0];
257                         alpha_v = vsub && j+1 < hp ?
258                             (a[0] + a[src->linesize[3]]) >> 1 : a[0];
259                         alpha = (alpha_v + alpha_h) >> 1;
260                     } else
261                         alpha = a[0];
262                     *d = (*d * (0xff - alpha) + *s++ * alpha + 128) >> 8;
263                     d++;
264                     a += 1 << hsub;
265                 }
266                 dp += dst->linesize[i];
267                 sp += src->linesize[i];
268                 ap += (1 << vsub) * src->linesize[3];
269             }
270         }
271     }
272 }
273
274 static int filter_frame_main(AVFilterLink *inlink, AVFrame *frame)
275 {
276     OverlayContext *s = inlink->dst->priv;
277
278     av_assert0(!s->main);
279     s->main         = frame;
280
281     return 0;
282 }
283
284 static int filter_frame_overlay(AVFilterLink *inlink, AVFrame *frame)
285 {
286     OverlayContext *s = inlink->dst->priv;
287
288     av_assert0(!s->over_next);
289     s->over_next    = frame;
290
291     return 0;
292 }
293
294 static int output_frame(AVFilterContext *ctx)
295 {
296     OverlayContext *s = ctx->priv;
297     AVFilterLink *outlink = ctx->outputs[0];
298     int ret = ff_filter_frame(outlink, s->main);
299     s->main = NULL;
300
301     return ret;
302 }
303
304 static int handle_overlay_eof(AVFilterContext *ctx)
305 {
306     OverlayContext *s = ctx->priv;
307     /* Repeat previous frame on secondary input */
308     if (s->over_prev && s->eof_action == EOF_ACTION_REPEAT)
309         blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
310     /* End both streams */
311     else if (s->eof_action == EOF_ACTION_ENDALL)
312         return AVERROR_EOF;
313     return output_frame(ctx);
314 }
315
316 static int request_frame(AVFilterLink *outlink)
317 {
318     AVFilterContext *ctx = outlink->src;
319     OverlayContext    *s = ctx->priv;
320     AVRational tb_main = ctx->inputs[MAIN]->time_base;
321     AVRational tb_over = ctx->inputs[OVERLAY]->time_base;
322     int ret = 0;
323
324     /* get a frame on the main input */
325     if (!s->main) {
326         ret = ff_request_frame(ctx->inputs[MAIN]);
327         if (ret < 0)
328             return ret;
329     }
330
331     /* get a new frame on the overlay input, on EOF check setting 'eof_action' */
332     if (!s->over_next) {
333         ret = ff_request_frame(ctx->inputs[OVERLAY]);
334         if (ret == AVERROR_EOF)
335            return handle_overlay_eof(ctx);
336         else if (ret < 0)
337             return ret;
338     }
339
340     while (s->main->pts != AV_NOPTS_VALUE &&
341            s->over_next->pts != AV_NOPTS_VALUE &&
342            av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main) < 0) {
343         av_frame_free(&s->over_prev);
344         FFSWAP(AVFrame*, s->over_prev, s->over_next);
345
346         ret = ff_request_frame(ctx->inputs[OVERLAY]);
347         if (ret == AVERROR_EOF)
348             return handle_overlay_eof(ctx);
349         else if (ret < 0)
350             return ret;
351     }
352
353     if (s->main->pts == AV_NOPTS_VALUE ||
354         s->over_next->pts == AV_NOPTS_VALUE ||
355         !av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main)) {
356         blend_frame(ctx, s->main, s->over_next, s->x, s->y);
357         av_frame_free(&s->over_prev);
358         FFSWAP(AVFrame*, s->over_prev, s->over_next);
359     } else if (s->over_prev) {
360         blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
361     }
362
363     return output_frame(ctx);
364 }
365
366 #define OFFSET(x) offsetof(OverlayContext, x)
367 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM
368 static const AVOption options[] = {
369     { "x", "Horizontal position of the left edge of the overlaid video on the "
370         "main video.",          OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
371     { "y", "Vertical position of the top edge of the overlaid video on the "
372         "main video.",          OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
373     { "eof_action", "Action to take when encountering EOF from secondary input ",
374         OFFSET(eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
375         EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
376         { "repeat", "Repeat the previous frame.",   0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
377         { "endall", "End both streams.",            0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
378         { "pass",   "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS },   .flags = FLAGS, "eof_action" },
379     { NULL },
380 };
381
382 static const AVClass overlay_class = {
383     .class_name = "overlay",
384     .item_name  = av_default_item_name,
385     .option     = options,
386     .version    = LIBAVUTIL_VERSION_INT,
387 };
388
389 static const AVFilterPad avfilter_vf_overlay_inputs[] = {
390     {
391         .name         = "main",
392         .type         = AVMEDIA_TYPE_VIDEO,
393         .config_props = config_input_main,
394         .filter_frame = filter_frame_main,
395         .needs_writable = 1,
396         .needs_fifo   = 1,
397     },
398     {
399         .name         = "overlay",
400         .type         = AVMEDIA_TYPE_VIDEO,
401         .config_props = config_input_overlay,
402         .filter_frame = filter_frame_overlay,
403         .needs_fifo   = 1,
404     },
405     { NULL }
406 };
407
408 static const AVFilterPad avfilter_vf_overlay_outputs[] = {
409     {
410         .name          = "default",
411         .type          = AVMEDIA_TYPE_VIDEO,
412         .config_props  = config_output,
413         .request_frame = request_frame,
414     },
415     { NULL }
416 };
417
418 AVFilter ff_vf_overlay = {
419     .name      = "overlay",
420     .description = NULL_IF_CONFIG_SMALL("Overlay a video source on top of the input."),
421
422     .uninit    = uninit,
423
424     .priv_size = sizeof(OverlayContext),
425     .priv_class = &overlay_class,
426
427     .query_formats = query_formats,
428
429     .inputs    = avfilter_vf_overlay_inputs,
430     .outputs   = avfilter_vf_overlay_outputs,
431 };