]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_pad.c
Merge commit '36ef5369ee9b336febc2c270f8718cec4476cb85'
[ffmpeg] / libavfilter / vf_pad.c
index 31702b73186a295fd7cabdd94ecfb7d9a44b47b6..3e9dfa2680b54c4177b6d9911cb4b34dac59a282 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "avfilter.h"
 #include "formats.h"
+#include "internal.h"
 #include "video.h"
 #include "libavutil/avstring.h"
 #include "libavutil/eval.h"
@@ -89,7 +90,7 @@ typedef struct {
     int needs_copy;
 } PadContext;
 
-static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+static av_cold int init(AVFilterContext *ctx, const char *args)
 {
     PadContext *pad = ctx->priv;
     char color_string[128] = "black";
@@ -183,7 +184,7 @@ static int config_input(AVFilterLink *inlink)
     pad->in_w = ff_draw_round_to_sub(&pad->draw, 0, -1, inlink->w);
     pad->in_h = ff_draw_round_to_sub(&pad->draw, 1, -1, inlink->h);
 
-    av_log(ctx, AV_LOG_INFO, "w:%d h:%d -> w:%d h:%d x:%d y:%d color:0x%02X%02X%02X%02X\n",
+    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d x:%d y:%d color:0x%02X%02X%02X%02X\n",
            inlink->w, inlink->h, pad->w, pad->h, pad->x, pad->y,
            pad->rgba_color[0], pad->rgba_color[1], pad->rgba_color[2], pad->rgba_color[3]);
 
@@ -220,11 +221,14 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int
     PadContext *pad = inlink->dst->priv;
     int align = (perms&AV_PERM_ALIGN) ? AVFILTER_ALIGN : 1;
 
-    AVFilterBufferRef *picref = avfilter_get_video_buffer(inlink->dst->outputs[0], perms,
-                                                       w + (pad->w - pad->in_w) + 4*align,
-                                                       h + (pad->h - pad->in_h));
+    AVFilterBufferRef *picref = ff_get_video_buffer(inlink->dst->outputs[0], perms,
+                                                    w + (pad->w - pad->in_w) + 4*align,
+                                                    h + (pad->h - pad->in_h));
     int plane;
 
+    if (!picref)
+        return NULL;
+
     picref->video->w = w;
     picref->video->h = h;
 
@@ -258,11 +262,15 @@ static int does_clip(PadContext *pad, AVFilterBufferRef *outpicref, int plane, i
     return 0;
 }
 
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 {
     PadContext *pad = inlink->dst->priv;
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
-    int plane;
+    AVFilterBufferRef *for_next_filter;
+    int plane, ret = 0;
+
+    if (!outpicref)
+        return AVERROR(ENOMEM);
 
     for (plane = 0; plane < 4 && outpicref->data[plane] && pad->draw.pixelstep[plane]; plane++) {
         int hsub = pad->draw.hsub[plane];
@@ -283,28 +291,44 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
           )
             break;
     }
-    pad->needs_copy= plane < 4 && outpicref->data[plane];
+    pad->needs_copy= plane < 4 && outpicref->data[plane] || !(outpicref->perms & AV_PERM_WRITE);
     if(pad->needs_copy){
         av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n");
         avfilter_unref_buffer(outpicref);
-        outpicref = avfilter_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
-                                                       FFMAX(inlink->w, pad->w),
-                                                       FFMAX(inlink->h, pad->h));
+        outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
+                                        FFMAX(inlink->w, pad->w),
+                                        FFMAX(inlink->h, pad->h));
+        if (!outpicref)
+            return AVERROR(ENOMEM);
+
         avfilter_copy_buffer_ref_props(outpicref, inpicref);
     }
 
-    inlink->dst->outputs[0]->out_buf = outpicref;
-
     outpicref->video->w = pad->w;
     outpicref->video->h = pad->h;
 
-    ff_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(outpicref, ~0));
+    for_next_filter = avfilter_ref_buffer(outpicref, ~0);
+    if (!for_next_filter) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter);
+    if (ret < 0)
+        goto fail;
+
+    inlink->dst->outputs[0]->out_buf = outpicref;
+    return 0;
+
+fail:
+    avfilter_unref_bufferp(&outpicref);
+    return ret;
 }
 
-static void draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice)
+static int draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice)
 {
     PadContext *pad = link->dst->priv;
-    int bar_y, bar_h = 0;
+    int bar_y, bar_h = 0, ret = 0;
 
     if        (slice_dir * before_slice ==  1 && y == pad->y) {
         /* top bar */
@@ -321,15 +345,17 @@ static void draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir,
                           link->dst->outputs[0]->out_buf->data,
                           link->dst->outputs[0]->out_buf->linesize,
                           0, bar_y, pad->w, bar_h);
-        ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir);
+        ret = ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir);
     }
+    return ret;
 }
 
-static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
+static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
 {
     PadContext *pad = link->dst->priv;
     AVFilterBufferRef *outpic = link->dst->outputs[0]->out_buf;
     AVFilterBufferRef *inpic = link->cur_buf;
+    int ret;
 
     y += pad->y;
 
@@ -337,7 +363,7 @@ static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
     h = ff_draw_round_to_sub(&pad->draw, 1, -1, h);
 
     if (!h)
-        return;
+        return 0;
     draw_send_bar_slice(link, y, h, slice_dir, 1);
 
     /* left border */
@@ -354,9 +380,11 @@ static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
     /* right border */
     ff_fill_rectangle(&pad->draw, &pad->color, outpic->data, outpic->linesize,
                       pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h);
-    ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
+    ret = ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
+    if (ret < 0)
+        return ret;
 
-    draw_send_bar_slice(link, y, h, slice_dir, -1);
+    return draw_send_bar_slice(link, y, h, slice_dir, -1);
 }
 
 AVFilter avfilter_vf_pad = {
@@ -367,16 +395,16 @@ AVFilter avfilter_vf_pad = {
     .init          = init,
     .query_formats = query_formats,
 
-    .inputs    = (const AVFilterPad[]) {{ .name       = "default",
-                                    .type             = AVMEDIA_TYPE_VIDEO,
-                                    .config_props     = config_input,
-                                    .get_video_buffer = get_video_buffer,
-                                    .start_frame      = start_frame,
-                                    .draw_slice       = draw_slice, },
-                                  { .name = NULL}},
-
-    .outputs   = (const AVFilterPad[]) {{ .name       = "default",
-                                    .type             = AVMEDIA_TYPE_VIDEO,
-                                    .config_props     = config_output, },
-                                  { .name = NULL}},
+    .inputs    = (const AVFilterPad[]) {{ .name             = "default",
+                                          .type             = AVMEDIA_TYPE_VIDEO,
+                                          .config_props     = config_input,
+                                          .get_video_buffer = get_video_buffer,
+                                          .start_frame      = start_frame,
+                                          .draw_slice       = draw_slice, },
+                                        { .name = NULL}},
+
+    .outputs   = (const AVFilterPad[]) {{ .name             = "default",
+                                          .type             = AVMEDIA_TYPE_VIDEO,
+                                          .config_props     = config_output, },
+                                        { .name = NULL}},
 };