Browse code

lavfi: add error handling to start_frame().

Anton Khirnov authored on 2012/07/09 00:29:42
Showing 26 changed files
... ...
@@ -258,8 +258,11 @@ struct AVFilterPad {
258 258
      * picture inside the link structure.
259 259
      *
260 260
      * Input video pads only.
261
+     *
262
+     * @return >= 0 on success, a negative AVERROR on error. picref will be
263
+     * unreferenced by the caller in case of error.
261 264
      */
262
-    void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
265
+    int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
263 266
 
264 267
     /**
265 268
      * Callback function to get a video buffer. If NULL, the filter system will
... ...
@@ -47,20 +47,16 @@ static av_cold void uninit(AVFilterContext *ctx)
47 47
         av_audio_fifo_free(sink->audio_fifo);
48 48
 }
49 49
 
50
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
50
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
51 51
 {
52 52
     BufferSinkContext *s = link->dst->priv;
53 53
 
54 54
     av_assert0(!s->cur_buf);
55 55
     s->cur_buf    = buf;
56 56
     link->cur_buf = NULL;
57
-};
58 57
 
59
-static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
60
-{
61
-    start_frame(link, buf);
62 58
     return 0;
63
-}
59
+};
64 60
 
65 61
 int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
66 62
 {
... ...
@@ -166,7 +162,7 @@ AVFilter avfilter_asink_abuffer = {
166 166
 
167 167
     .inputs    = (const AVFilterPad[]) {{ .name           = "default",
168 168
                                           .type           = AVMEDIA_TYPE_AUDIO,
169
-                                          .filter_samples = filter_samples,
169
+                                          .filter_samples = start_frame,
170 170
                                           .min_perms      = AV_PERM_READ,
171 171
                                           .needs_fifo     = 1 },
172 172
                                         { .name = NULL }},
... ...
@@ -76,6 +76,7 @@ static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
76 76
 {
77 77
     FifoContext *fifo = inlink->dst->priv;
78 78
 
79
+    inlink->cur_buf = NULL;
79 80
     fifo->last->next = av_mallocz(sizeof(Buf));
80 81
     if (!fifo->last->next) {
81 82
         avfilter_unref_buffer(buf);
... ...
@@ -88,12 +89,6 @@ static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
88 88
     return 0;
89 89
 }
90 90
 
91
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
92
-{
93
-    add_to_queue(inlink, buf);
94
-    inlink->cur_buf = NULL;
95
-}
96
-
97 91
 static void queue_pop(FifoContext *s)
98 92
 {
99 93
     Buf *tmp = s->root.next->next;
... ...
@@ -272,7 +267,7 @@ AVFilter avfilter_vf_fifo = {
272 272
     .inputs    = (const AVFilterPad[]) {{ .name            = "default",
273 273
                                           .type            = AVMEDIA_TYPE_VIDEO,
274 274
                                           .get_video_buffer= ff_null_get_video_buffer,
275
-                                          .start_frame     = start_frame,
275
+                                          .start_frame     = add_to_queue,
276 276
                                           .draw_slice      = draw_slice,
277 277
                                           .end_frame       = end_frame,
278 278
                                           .rej_perms       = AV_PERM_REUSE2, },
... ...
@@ -69,6 +69,9 @@ struct AVFilterPad {
69 69
      * picture inside the link structure.
70 70
      *
71 71
      * Input video pads only.
72
+     *
73
+     * @return >= 0 on success, a negative AVERROR on error. picref will be
74
+     * unreferenced by the caller in case of error.
72 75
      */
73 76
     void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
74 77
 
... ...
@@ -63,14 +63,18 @@ static void split_uninit(AVFilterContext *ctx)
63 63
         av_freep(&ctx->output_pads[i].name);
64 64
 }
65 65
 
66
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
66
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
67 67
 {
68 68
     AVFilterContext *ctx = inlink->dst;
69
-    int i;
69
+    int i, ret = 0;
70 70
 
71
-    for (i = 0; i < ctx->nb_outputs; i++)
72
-        ff_start_frame(ctx->outputs[i],
73
-                       avfilter_ref_buffer(picref, ~AV_PERM_WRITE));
71
+    for (i = 0; i < ctx->nb_outputs; i++) {
72
+        ret = ff_start_frame(ctx->outputs[i],
73
+                             avfilter_ref_buffer(picref, ~AV_PERM_WRITE));
74
+        if (ret < 0)
75
+            break;
76
+    }
77
+    return ret;
74 78
 }
75 79
 
76 80
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
... ...
@@ -64,13 +64,13 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
64 64
     return 0;
65 65
 }
66 66
 
67
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
67
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
68 68
 {
69 69
     AspectContext *aspect = link->dst->priv;
70 70
 
71 71
     picref->video->pixel_aspect = aspect->aspect;
72 72
     link->cur_buf = NULL;
73
-    ff_start_frame(link->dst->outputs[0], picref);
73
+    return ff_start_frame(link->dst->outputs[0], picref);
74 74
 }
75 75
 
76 76
 #if CONFIG_SETDAR_FILTER
... ...
@@ -240,7 +240,7 @@ static int config_output(AVFilterLink *link)
240 240
     return 0;
241 241
 }
242 242
 
243
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
243
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
244 244
 {
245 245
     AVFilterContext *ctx = link->dst;
246 246
     CropContext *crop = ctx->priv;
... ...
@@ -248,6 +248,9 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
248 248
     int i;
249 249
 
250 250
     ref2 = avfilter_ref_buffer(picref, ~0);
251
+    if (!ref2)
252
+        return AVERROR(ENOMEM);
253
+
251 254
     ref2->video->w = crop->w;
252 255
     ref2->video->h = crop->h;
253 256
 
... ...
@@ -291,7 +294,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
291 291
         ref2->data[3] += crop->x * crop->max_step[3];
292 292
     }
293 293
 
294
-    ff_start_frame(link->dst->outputs[0], ref2);
294
+    return ff_start_frame(link->dst->outputs[0], ref2);
295 295
 }
296 296
 
297 297
 static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -214,22 +214,35 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
214 214
     return 0;
215 215
 }
216 216
 
217
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
217
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
218 218
 {
219 219
     AVFilterLink *outlink = inlink->dst->outputs[0];
220
-    AVFilterBufferRef *outpicref;
220
+    AVFilterBufferRef *outpicref = NULL;
221
+    int ret = 0;
221 222
 
222 223
     if (inpicref->perms & AV_PERM_PRESERVE) {
223 224
         outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE,
224 225
                                         outlink->w, outlink->h);
226
+        if (!outpicref)
227
+            return AVERROR(ENOMEM);
228
+
225 229
         avfilter_copy_buffer_ref_props(outpicref, inpicref);
226 230
         outpicref->video->w = outlink->w;
227 231
         outpicref->video->h = outlink->h;
228
-    } else
232
+    } else {
229 233
         outpicref = avfilter_ref_buffer(inpicref, ~0);
234
+        if (!outpicref)
235
+            return AVERROR(ENOMEM);
236
+    }
237
+
238
+    ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
239
+    if (ret < 0) {
240
+        avfilter_unref_bufferp(&outpicref);
241
+        return ret;
242
+    }
230 243
 
231 244
     outlink->out_buf = outpicref;
232
-    ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
245
+    return 0;
233 246
 }
234 247
 
235 248
 static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
... ...
@@ -808,16 +808,16 @@ static inline int normalize_double(int *n, double d)
808 808
     return ret;
809 809
 }
810 810
 
811
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
811
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
812 812
 {
813 813
     AVFilterContext *ctx = inlink->dst;
814 814
     DrawTextContext *dtext = ctx->priv;
815 815
     AVFilterBufferRef *buf_out;
816
-    int fail = 0;
816
+    int ret = 0;
817 817
 
818
-    if (dtext_prepare_text(ctx) < 0) {
818
+    if ((ret = dtext_prepare_text(ctx)) < 0) {
819 819
         av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
820
-        fail = 1;
820
+        return ret;
821 821
     }
822 822
 
823 823
     dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ?
... ...
@@ -829,8 +829,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
829 829
     dtext->var_values[VAR_X] =
830 830
         av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
831 831
 
832
-    dtext->draw = fail ? 0 :
833
-        av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng);
832
+    dtext->draw = av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng);
834 833
 
835 834
     normalize_double(&dtext->x, dtext->var_values[VAR_X]);
836 835
     normalize_double(&dtext->y, dtext->var_values[VAR_Y]);
... ...
@@ -852,7 +851,10 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
852 852
             dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h);
853 853
 
854 854
     buf_out = avfilter_ref_buffer(inpicref, ~0);
855
-    ff_start_frame(inlink->dst->outputs[0], buf_out);
855
+    if (!buf_out)
856
+        return AVERROR(ENOMEM);
857
+
858
+    return ff_start_frame(inlink->dst->outputs[0], buf_out);
856 859
 }
857 860
 
858 861
 static void end_frame(AVFilterLink *inlink)
... ...
@@ -116,18 +116,32 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int
116 116
     return ff_get_video_buffer(outlink, perms, w, h);
117 117
 }
118 118
 
119
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
119
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
120 120
 {
121 121
     AVFilterContext   *ctx        = inlink->dst;
122 122
     AVFilterLink      *outlink    = ctx->outputs[0];
123 123
 
124 124
     AVFilterBufferRef *outpicref, *for_next_filter;
125
+    int ret = 0;
125 126
 
126 127
     outpicref = avfilter_ref_buffer(inpicref, ~0);
127
-    outlink->out_buf = outpicref;
128
+    if (!outpicref)
129
+        return AVERROR(ENOMEM);
128 130
 
129 131
     for_next_filter = avfilter_ref_buffer(outpicref, ~0);
130
-    ff_start_frame(outlink, for_next_filter);
132
+    if (!for_next_filter) {
133
+        avfilter_unref_bufferp(&outpicref);
134
+        return AVERROR(ENOMEM);
135
+    }
136
+
137
+    ret = ff_start_frame(outlink, for_next_filter);
138
+    if (ret < 0) {
139
+        avfilter_unref_bufferp(&outpicref);
140
+        return ret;
141
+    }
142
+
143
+    outlink->out_buf = outpicref;
144
+    return 0;
131 145
 }
132 146
 
133 147
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
... ...
@@ -243,8 +243,9 @@ static void end_frame(AVFilterLink *inlink)
243 243
     s->pts = s->first_pts + av_rescale_q(s->frames_out, outlink->time_base, inlink->time_base);
244 244
 }
245 245
 
246
-static void null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
246
+static int null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
247 247
 {
248
+    return 0;
248 249
 }
249 250
 
250 251
 static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -180,21 +180,34 @@ static int config_input(AVFilterLink *inlink)
180 180
     return 0;
181 181
 }
182 182
 
183
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
183
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
184 184
 {
185 185
     AVFilterLink *outlink = inlink->dst->outputs[0];
186
-    AVFilterBufferRef *outpicref;
186
+    AVFilterBufferRef *outpicref = NULL;
187
+    int ret = 0;
187 188
 
188 189
     if (inpicref->perms & AV_PERM_PRESERVE) {
189 190
         outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
191
+        if (!outpicref)
192
+            return AVERROR(ENOMEM);
193
+
190 194
         avfilter_copy_buffer_ref_props(outpicref, inpicref);
191 195
         outpicref->video->w = outlink->w;
192 196
         outpicref->video->h = outlink->h;
193
-    } else
197
+    } else {
194 198
         outpicref = avfilter_ref_buffer(inpicref, ~0);
199
+        if (!outpicref)
200
+            return AVERROR(ENOMEM);
201
+    }
202
+
203
+    ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
204
+    if (ret < 0) {
205
+        avfilter_unref_bufferp(&outpicref);
206
+        return ret;
207
+    }
195 208
 
196 209
     outlink->out_buf = outpicref;
197
-    ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
210
+    return 0;
198 211
 }
199 212
 
200 213
 static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
... ...
@@ -208,7 +208,7 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w,
208 208
     return ff_get_video_buffer(link->dst->outputs[0], perms, w, h);
209 209
 }
210 210
 
211
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
211
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
212 212
 {
213 213
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
214 214
     AVFilterContext *ctx = inlink->dst;
... ...
@@ -228,10 +228,10 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
228 228
             over->overpicref = old;
229 229
     }
230 230
 
231
-    ff_start_frame(inlink->dst->outputs[0], outpicref);
231
+    return ff_start_frame(inlink->dst->outputs[0], outpicref);
232 232
 }
233 233
 
234
-static void start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
234
+static int start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
235 235
 {
236 236
     AVFilterContext *ctx = inlink->dst;
237 237
     OverlayContext *over = ctx->priv;
... ...
@@ -239,6 +239,7 @@ static void start_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *inpicre
239 239
     over->overpicref = inpicref;
240 240
     over->overpicref->pts = av_rescale_q(inpicref->pts, ctx->inputs[OVERLAY]->time_base,
241 241
                                          ctx->outputs[0]->time_base);
242
+    return 0;
242 243
 }
243 244
 
244 245
 static void blend_slice(AVFilterContext *ctx,
... ...
@@ -299,12 +299,15 @@ static int does_clip(PadContext *pad, AVFilterBufferRef *outpicref, int plane, i
299 299
     return 0;
300 300
 }
301 301
 
302
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
302
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
303 303
 {
304 304
     PadContext *pad = inlink->dst->priv;
305 305
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
306 306
     AVFilterBufferRef *for_next_filter;
307
-    int plane;
307
+    int plane, ret = 0;
308
+
309
+    if (!outpicref)
310
+        return AVERROR(ENOMEM);
308 311
 
309 312
     for (plane = 0; plane < 4 && outpicref->data[plane]; plane++) {
310 313
         int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0;
... ...
@@ -332,16 +335,31 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
332 332
         outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
333 333
                                         FFMAX(inlink->w, pad->w),
334 334
                                         FFMAX(inlink->h, pad->h));
335
+        if (!outpicref)
336
+            return AVERROR(ENOMEM);
337
+
335 338
         avfilter_copy_buffer_ref_props(outpicref, inpicref);
336 339
     }
337 340
 
338
-    inlink->dst->outputs[0]->out_buf = outpicref;
339
-
340 341
     outpicref->video->w = pad->w;
341 342
     outpicref->video->h = pad->h;
342 343
 
343 344
     for_next_filter = avfilter_ref_buffer(outpicref, ~0);
344
-    ff_start_frame(inlink->dst->outputs[0], for_next_filter);
345
+    if (!for_next_filter) {
346
+        ret = AVERROR(ENOMEM);
347
+        goto fail;
348
+    }
349
+
350
+    ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter);
351
+    if (ret < 0)
352
+        goto fail;
353
+
354
+    inlink->dst->outputs[0]->out_buf = outpicref;
355
+    return 0;
356
+
357
+fail:
358
+    avfilter_unref_bufferp(&outpicref);
359
+    return ret;
345 360
 }
346 361
 
347 362
 static void end_frame(AVFilterLink *link)
... ...
@@ -51,16 +51,18 @@ static int config_props(AVFilterLink *inlink)
51 51
     return 0;
52 52
 }
53 53
 
54
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
54
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
55 55
 {
56 56
     PixdescTestContext *priv = inlink->dst->priv;
57 57
     AVFilterLink *outlink    = inlink->dst->outputs[0];
58 58
     AVFilterBufferRef *outpicref;
59
-    int i;
59
+    int i, ret = 0;
60
+
61
+    outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE,
62
+                                    outlink->w, outlink->h);
63
+    if (!outpicref)
64
+        return AVERROR(ENOMEM);
60 65
 
61
-    outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE,
62
-                                           outlink->w, outlink->h);
63
-    outpicref = outlink->out_buf;
64 66
     avfilter_copy_buffer_ref_props(outpicref, picref);
65 67
 
66 68
     for (i = 0; i < 4; i++) {
... ...
@@ -78,7 +80,14 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
78 78
         priv->pix_desc->flags & PIX_FMT_PSEUDOPAL)
79 79
         memcpy(outpicref->data[1], outpicref->data[1], 256*4);
80 80
 
81
-    ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
81
+    ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
82
+    if (ret < 0) {
83
+        avfilter_unref_bufferp(&outpicref);
84
+        return ret;
85
+    }
86
+
87
+    outlink->out_buf = outpicref;
88
+    return 0;
82 89
 }
83 90
 
84 91
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
... ...
@@ -252,26 +252,28 @@ fail:
252 252
     return ret;
253 253
 }
254 254
 
255
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
255
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
256 256
 {
257 257
     ScaleContext *scale = link->dst->priv;
258 258
     AVFilterLink *outlink = link->dst->outputs[0];
259 259
     AVFilterBufferRef *outpicref;
260
+    int ret = 0;
260 261
 
261 262
     if (!scale->sws) {
262
-        ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
263
-        return;
263
+        return ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
264 264
     }
265 265
 
266 266
     scale->hsub = av_pix_fmt_descriptors[link->format].log2_chroma_w;
267 267
     scale->vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
268 268
 
269 269
     outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
270
+    if (!outpicref)
271
+        return AVERROR(ENOMEM);
272
+
270 273
     avfilter_copy_buffer_ref_props(outpicref, picref);
271 274
     outpicref->video->w = outlink->w;
272 275
     outpicref->video->h = outlink->h;
273 276
 
274
-    outlink->out_buf = outpicref;
275 277
 
276 278
     av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den,
277 279
               (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w,
... ...
@@ -279,7 +281,14 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
279 279
               INT_MAX);
280 280
 
281 281
     scale->slice_y = 0;
282
-    ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
282
+    ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
283
+    if (ret < 0) {
284
+        avfilter_unref_bufferp(&outpicref);
285
+        return ret;
286
+    }
287
+
288
+    outlink->out_buf = outpicref;
289
+    return 0;
283 290
 }
284 291
 
285 292
 static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -227,7 +227,7 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref)
227 227
     return res;
228 228
 }
229 229
 
230
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
230
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
231 231
 {
232 232
     SelectContext *select = inlink->dst->priv;
233 233
 
... ...
@@ -241,10 +241,12 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
241 241
             else
242 242
                 av_fifo_generic_write(select->pending_frames, &picref,
243 243
                                       sizeof(picref), NULL);
244
-            return;
244
+            return 0;
245 245
         }
246
-        ff_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0));
246
+        return ff_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0));
247 247
     }
248
+
249
+    return 0;
248 250
 }
249 251
 
250 252
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
... ...
@@ -101,12 +101,15 @@ static int config_input(AVFilterLink *inlink)
101 101
 #define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
102 102
 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
103 103
 
104
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
104
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
105 105
 {
106 106
     SetPTSContext *setpts = inlink->dst->priv;
107 107
     double d;
108 108
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
109 109
 
110
+    if (!outpicref)
111
+        return AVERROR(ENOMEM);
112
+
110 113
     if (isnan(setpts->var_values[VAR_STARTPTS]))
111 114
         setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts);
112 115
 
... ...
@@ -130,7 +133,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
130 130
     setpts->var_values[VAR_N] += 1.0;
131 131
     setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
132 132
     setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
133
-    ff_start_frame(inlink->dst->outputs[0], outpicref);
133
+    return ff_start_frame(inlink->dst->outputs[0], outpicref);
134 134
 }
135 135
 
136 136
 static av_cold void uninit(AVFilterContext *ctx)
... ...
@@ -104,7 +104,7 @@ static int config_output_props(AVFilterLink *outlink)
104 104
     return 0;
105 105
 }
106 106
 
107
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
107
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
108 108
 {
109 109
     AVFilterContext *ctx = inlink->dst;
110 110
     AVFilterLink *outlink = ctx->outputs[0];
... ...
@@ -118,7 +118,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
118 118
     }
119 119
     inlink->cur_buf = NULL;
120 120
 
121
-    ff_start_frame(outlink, picref);
121
+    return ff_start_frame(outlink, picref);
122 122
 }
123 123
 
124 124
 AVFilter avfilter_vf_settb = {
... ...
@@ -59,7 +59,7 @@ static int config_props(AVFilterLink *link)
59 59
     return 0;
60 60
 }
61 61
 
62
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
62
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
63 63
 {
64 64
     SliceContext *slice = link->dst->priv;
65 65
 
... ...
@@ -75,7 +75,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
75 75
     av_log(link->dst, AV_LOG_DEBUG, "h:%d\n", slice->h);
76 76
     link->cur_buf = NULL;
77 77
 
78
-    ff_start_frame(link->dst->outputs[0], picref);
78
+    return ff_start_frame(link->dst->outputs[0], picref);
79 79
 }
80 80
 
81 81
 static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -117,12 +117,15 @@ static int config_props_output(AVFilterLink *outlink)
117 117
     return 0;
118 118
 }
119 119
 
120
-static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
120
+static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
121 121
 {
122 122
     AVFilterLink *outlink = inlink->dst->outputs[0];
123 123
 
124 124
     outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE,
125 125
                                            outlink->w, outlink->h);
126
+    if (!outlink->out_buf)
127
+        return AVERROR(ENOMEM);
128
+
126 129
     outlink->out_buf->pts = picref->pts;
127 130
 
128 131
     if (picref->video->pixel_aspect.num == 0) {
... ...
@@ -132,7 +135,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
132 132
         outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num;
133 133
     }
134 134
 
135
-    ff_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
135
+    return ff_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
136 136
 }
137 137
 
138 138
 static void end_frame(AVFilterLink *inlink)
... ...
@@ -64,7 +64,7 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms,
64 64
     return picref;
65 65
 }
66 66
 
67
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref)
67
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref)
68 68
 {
69 69
     FlipContext *flip = link->dst->priv;
70 70
     AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
... ...
@@ -79,7 +79,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref)
79 79
         }
80 80
     }
81 81
 
82
-    ff_start_frame(link->dst->outputs[0], outpicref);
82
+    return ff_start_frame(link->dst->outputs[0], outpicref);
83 83
 }
84 84
 
85 85
 static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -201,7 +201,7 @@ static void return_frame(AVFilterContext *ctx, int is_second)
201 201
     yadif->frame_pending = (yadif->mode&1) && !is_second;
202 202
 }
203 203
 
204
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
204
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
205 205
 {
206 206
     AVFilterContext *ctx = link->dst;
207 207
     YADIFContext *yadif = ctx->priv;
... ...
@@ -216,7 +216,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
216 216
     yadif->next = picref;
217 217
 
218 218
     if (!yadif->cur)
219
-        return;
219
+        return 0;
220 220
 
221 221
     if (yadif->auto_enable && !yadif->cur->video->interlaced) {
222 222
         yadif->out  = avfilter_ref_buffer(yadif->cur, AV_PERM_READ);
... ...
@@ -224,8 +224,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
224 224
         yadif->prev = NULL;
225 225
         if (yadif->out->pts != AV_NOPTS_VALUE)
226 226
             yadif->out->pts *= 2;
227
-        ff_start_frame(ctx->outputs[0], yadif->out);
228
-        return;
227
+        return ff_start_frame(ctx->outputs[0], yadif->out);
229 228
     }
230 229
 
231 230
     if (!yadif->prev)
... ...
@@ -238,7 +237,7 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
238 238
     yadif->out->video->interlaced = 0;
239 239
     if (yadif->out->pts != AV_NOPTS_VALUE)
240 240
         yadif->out->pts *= 2;
241
-    ff_start_frame(ctx->outputs[0], yadif->out);
241
+    return ff_start_frame(ctx->outputs[0], yadif->out);
242 242
 }
243 243
 
244 244
 static void end_frame(AVFilterLink *link)
... ...
@@ -160,13 +160,15 @@ AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int
160 160
     return ret;
161 161
 }
162 162
 
163
-void ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
163
+int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
164 164
 {
165 165
     AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~0);
166
-    ff_start_frame(link->dst->outputs[0], buf_out);
166
+    if (!buf_out)
167
+        return AVERROR(ENOMEM);
168
+    return ff_start_frame(link->dst->outputs[0], buf_out);
167 169
 }
168 170
 
169
-static void default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
171
+static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
170 172
 {
171 173
     AVFilterLink *outlink = NULL;
172 174
 
... ...
@@ -175,18 +177,29 @@ static void default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
175 175
 
176 176
     if (outlink) {
177 177
         outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
178
+        if (!outlink->out_buf)
179
+            return AVERROR(ENOMEM);
180
+
178 181
         avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
179
-        ff_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
182
+        return ff_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
180 183
     }
184
+    return 0;
185
+}
186
+
187
+static void clear_link(AVFilterLink *link)
188
+{
189
+    avfilter_unref_bufferp(&link->cur_buf);
190
+    avfilter_unref_bufferp(&link->src_buf);
191
+    avfilter_unref_bufferp(&link->out_buf);
181 192
 }
182 193
 
183 194
 /* XXX: should we do the duplicating of the picture ref here, instead of
184 195
  * forcing the source filter to do it? */
185
-void ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
196
+int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
186 197
 {
187
-    void (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
198
+    int (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
188 199
     AVFilterPad *dst = link->dstpad;
189
-    int perms = picref->perms;
200
+    int ret, perms = picref->perms;
190 201
 
191 202
     FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1);
192 203
 
... ...
@@ -203,13 +216,22 @@ void ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
203 203
                 link->dstpad->min_perms, link->dstpad->rej_perms);
204 204
 
205 205
         link->cur_buf = ff_get_video_buffer(link, dst->min_perms, link->w, link->h);
206
+        if (!link->cur_buf) {
207
+            avfilter_unref_bufferp(&picref);
208
+            return AVERROR(ENOMEM);
209
+        }
210
+
206 211
         link->src_buf = picref;
207 212
         avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
208 213
     }
209 214
     else
210 215
         link->cur_buf = picref;
211 216
 
212
-    start_frame(link, link->cur_buf);
217
+    ret = start_frame(link, link->cur_buf);
218
+    if (ret < 0)
219
+        clear_link(link);
220
+
221
+    return ret;
213 222
 }
214 223
 
215 224
 void ff_null_end_frame(AVFilterLink *link)
... ...
@@ -238,14 +260,7 @@ void ff_end_frame(AVFilterLink *link)
238 238
 
239 239
     end_frame(link);
240 240
 
241
-    /* unreference the source picture if we're feeding the destination filter
242
-     * a copied version dues to permission issues */
243
-    if (link->src_buf) {
244
-        avfilter_unref_buffer(link->src_buf);
245
-        link->src_buf = NULL;
246
-    }
247
-    avfilter_unref_bufferp(&link->cur_buf);
248
-    avfilter_unref_bufferp(&link->out_buf);
241
+    clear_link(link);
249 242
 }
250 243
 
251 244
 void ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
... ...
@@ -39,7 +39,7 @@ AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w
39 39
 AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms,
40 40
                                        int w, int h);
41 41
 
42
-void ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
42
+int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
43 43
 void ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
44 44
 void ff_null_end_frame(AVFilterLink *link);
45 45
 
... ...
@@ -51,8 +51,11 @@ void ff_null_end_frame(AVFilterLink *link);
51 51
  *               frame need only be valid once draw_slice() is called for that
52 52
  *               portion. The receiving filter will free this reference when
53 53
  *               it no longer needs it.
54
+ *
55
+ * @return >= 0 on success, a negative AVERROR on error. This function will
56
+ * unreference picref in case of error.
54 57
  */
55
-void ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
58
+int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
56 59
 
57 60
 /**
58 61
  * Notify the next filter that the current frame has finished.
... ...
@@ -19,8 +19,9 @@
19 19
 #include "avfilter.h"
20 20
 #include "internal.h"
21 21
 
22
-static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
22
+static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
23 23
 {
24
+    return 0;
24 25
 }
25 26
 
26 27
 static void end_frame(AVFilterLink *link)