lavfi: add error handling to end_frame().
[ffmpeg.git] / libavfilter / vf_overlay.c
index 1c04ecd..a0c423d 100644 (file)
@@ -3,20 +3,20 @@
  * Copyright (c) 2010 Baptiste Coudurier
  * Copyright (c) 2007 Bobby Bingham
  *
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
  */
 
 #include "avfilter.h"
+#include "formats.h"
 #include "libavutil/eval.h"
 #include "libavutil/avstring.h"
 #include "libavutil/pixdesc.h"
-#include "libavcore/imgutils.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/mathematics.h"
 #include "internal.h"
+#include "video.h"
 
-static const char *var_names[] = {
+static const char *const var_names[] = {
     "E",
     "PHI",
     "PI",
@@ -68,7 +71,7 @@ typedef struct {
     char x_expr[256], y_expr[256];
 } OverlayContext;
 
-static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+static av_cold int init(AVFilterContext *ctx, const char *args)
 {
     OverlayContext *over = ctx->priv;
 
@@ -93,12 +96,12 @@ static int query_formats(AVFilterContext *ctx)
 {
     const enum PixelFormat inout_pix_fmts[] = { PIX_FMT_YUV420P,  PIX_FMT_NONE };
     const enum PixelFormat blend_pix_fmts[] = { PIX_FMT_YUVA420P, PIX_FMT_NONE };
-    AVFilterFormats *inout_formats = avfilter_make_format_list(inout_pix_fmts);
-    AVFilterFormats *blend_formats = avfilter_make_format_list(blend_pix_fmts);
+    AVFilterFormats *inout_formats = ff_make_format_list(inout_pix_fmts);
+    AVFilterFormats *blend_formats = ff_make_format_list(blend_pix_fmts);
 
-    avfilter_formats_ref(inout_formats, &ctx->inputs [MAIN   ]->out_formats);
-    avfilter_formats_ref(blend_formats, &ctx->inputs [OVERLAY]->out_formats);
-    avfilter_formats_ref(inout_formats, &ctx->outputs[MAIN   ]->in_formats );
+    ff_formats_ref(inout_formats, &ctx->inputs [MAIN   ]->out_formats);
+    ff_formats_ref(blend_formats, &ctx->inputs [OVERLAY]->out_formats);
+    ff_formats_ref(inout_formats, &ctx->outputs[MAIN   ]->in_formats );
 
     return 0;
 }
@@ -148,7 +151,7 @@ static int config_input_overlay(AVFilterLink *inlink)
         goto fail;
     over->x = res;
 
-    av_log(ctx, AV_LOG_INFO,
+    av_log(ctx, AV_LOG_VERBOSE,
            "main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s\n",
            ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,
            av_pix_fmt_descriptors[ctx->inputs[MAIN]->format].name,
@@ -187,7 +190,7 @@ static int config_output(AVFilterLink *outlink)
                       av_gcd((int64_t)tb1.num * tb2.den,
                              (int64_t)tb2.num * tb1.den),
                       (int64_t)tb1.den * tb2.den, INT_MAX);
-    av_log(ctx, AV_LOG_INFO,
+    av_log(ctx, AV_LOG_VERBOSE,
            "main_tb:%d/%d overlay_tb:%d/%d -> tb:%d/%d exact:%d\n",
            tb1.num, tb1.den, tb2.num, tb2.den, tb->num, tb->den, exact);
     if (!exact)
@@ -202,21 +205,22 @@ static int config_output(AVFilterLink *outlink)
 
 static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w, int h)
 {
-    return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
+    return ff_get_video_buffer(link->dst->outputs[0], perms, w, h);
 }
 
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 {
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
     AVFilterContext *ctx = inlink->dst;
     OverlayContext *over = ctx->priv;
 
-    inlink->dst->outputs[0]->out_buf = outpicref;
+    outpicref->pts = av_rescale_q(outpicref->pts, ctx->inputs[MAIN]->time_base,
+                                  ctx->outputs[0]->time_base);
 
     if (!over->overpicref || over->overpicref->pts < outpicref->pts) {
         AVFilterBufferRef *old = over->overpicref;
         over->overpicref = NULL;
-        avfilter_request_frame(ctx->inputs[OVERLAY]);
+        ff_request_frame(ctx->inputs[OVERLAY]);
         if (over->overpicref) {
             if (old)
                 avfilter_unref_buffer(old);
@@ -224,10 +228,10 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
             over->overpicref = old;
     }
 
-    avfilter_start_frame(inlink->dst->outputs[0], outpicref);
+    return ff_start_frame(inlink->dst->outputs[0], outpicref);
 }
 
-static void start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 {
     AVFilterContext *ctx = inlink->dst;
     OverlayContext *over = ctx->priv;
@@ -235,6 +239,7 @@ static void start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicre
     over->overpicref = inpicref;
     over->overpicref->pts = av_rescale_q(inpicref->pts, ctx->inputs[OVERLAY]->time_base,
                                          ctx->outputs[0]->time_base);
+    return 0;
 }
 
 static void blend_slice(AVFilterContext *ctx,
@@ -315,16 +320,13 @@ static void blend_slice(AVFilterContext *ctx,
     }
 }
 
-static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
 {
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
-    AVFilterBufferRef *outpicref = outlink->out_buf;
+    AVFilterBufferRef *outpicref = inlink->cur_buf;
     OverlayContext *over = ctx->priv;
 
-    outpicref->pts = av_rescale_q(outpicref->pts, ctx->inputs[MAIN]->time_base,
-                                  outlink->time_base);
-
     if (over->overpicref &&
         !(over->x >= outpicref->video->w || over->y >= outpicref->video->h ||
           y+h < over->y || y >= over->y + over->overpicref->video->h)) {
@@ -332,18 +334,35 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
                     over->overpicref->video->w, over->overpicref->video->h,
                     y, outpicref->video->w, h);
     }
-    avfilter_draw_slice(outlink, y, h, slice_dir);
+    return ff_draw_slice(outlink, y, h, slice_dir);
 }
 
-static void end_frame(AVFilterLink *inlink)
+static int end_frame(AVFilterLink *inlink)
 {
-    avfilter_end_frame(inlink->dst->outputs[0]);
-    avfilter_unref_buffer(inlink->cur_buf);
+    return ff_end_frame(inlink->dst->outputs[0]);
 }
 
-static void null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { }
+static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+{
+    return 0;
+}
 
-static void null_end_frame(AVFilterLink *inlink) { }
+static int null_end_frame(AVFilterLink *inlink)
+{
+    return 0;
+}
+
+static int poll_frame(AVFilterLink *link)
+{
+    AVFilterContext   *s = link->src;
+    OverlayContext *over = s->priv;
+    int ret = ff_poll_frame(s->inputs[OVERLAY]);
+
+    if (ret == AVERROR_EOF)
+        ret = !!over->overpicref;
+
+    return ret && ff_poll_frame(s->inputs[MAIN]);
+}
 
 AVFilter avfilter_vf_overlay = {
     .name      = "overlay",
@@ -356,26 +375,27 @@ AVFilter avfilter_vf_overlay = {
 
     .query_formats = query_formats,
 
-    .inputs    = (AVFilterPad[]) {{ .name            = "main",
-                                    .type            = AVMEDIA_TYPE_VIDEO,
-                                    .start_frame     = start_frame,
-                                    .get_video_buffer= get_video_buffer,
-                                    .config_props    = config_input_main,
-                                    .draw_slice      = draw_slice,
-                                    .end_frame       = end_frame,
-                                    .min_perms       = AV_PERM_READ,
-                                    .rej_perms       = AV_PERM_REUSE2|AV_PERM_PRESERVE, },
-                                  { .name            = "overlay",
-                                    .type            = AVMEDIA_TYPE_VIDEO,
-                                    .start_frame     = start_frame_overlay,
-                                    .config_props    = config_input_overlay,
-                                    .draw_slice      = null_draw_slice,
-                                    .end_frame       = null_end_frame,
-                                    .min_perms       = AV_PERM_READ,
-                                    .rej_perms       = AV_PERM_REUSE2, },
-                                  { .name = NULL}},
-    .outputs   = (AVFilterPad[]) {{ .name            = "default",
-                                    .type            = AVMEDIA_TYPE_VIDEO,
-                                    .config_props    = config_output, },
-                                  { .name = NULL}},
+    .inputs    = (const AVFilterPad[]) {{ .name            = "main",
+                                          .type            = AVMEDIA_TYPE_VIDEO,
+                                          .start_frame     = start_frame,
+                                          .get_video_buffer= get_video_buffer,
+                                          .config_props    = config_input_main,
+                                          .draw_slice      = draw_slice,
+                                          .end_frame       = end_frame,
+                                          .min_perms       = AV_PERM_READ,
+                                          .rej_perms       = AV_PERM_REUSE2|AV_PERM_PRESERVE, },
+                                        { .name            = "overlay",
+                                          .type            = AVMEDIA_TYPE_VIDEO,
+                                          .start_frame     = start_frame_overlay,
+                                          .config_props    = config_input_overlay,
+                                          .draw_slice      = null_draw_slice,
+                                          .end_frame       = null_end_frame,
+                                          .min_perms       = AV_PERM_READ,
+                                          .rej_perms       = AV_PERM_REUSE2, },
+                                        { .name = NULL}},
+    .outputs   = (const AVFilterPad[]) {{ .name            = "default",
+                                          .type            = AVMEDIA_TYPE_VIDEO,
+                                          .config_props    = config_output,
+                                          .poll_frame      = poll_frame },
+                                        { .name = NULL}},
 };