Browse code

lavfi: add error handling to filter_samples().

Anton Khirnov authored on 2012/07/03 03:13:40
Showing 15 changed files
... ...
@@ -311,9 +311,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples)
311 311
     if (s->next_pts != AV_NOPTS_VALUE)
312 312
         s->next_pts += nb_samples;
313 313
 
314
-    ff_filter_samples(outlink, out_buf);
315
-
316
-    return 0;
314
+    return ff_filter_samples(outlink, out_buf);
317 315
 }
318 316
 
319 317
 /**
... ...
@@ -454,31 +452,37 @@ static int request_frame(AVFilterLink *outlink)
454 454
     return output_frame(outlink, available_samples);
455 455
 }
456 456
 
457
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
457
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
458 458
 {
459 459
     AVFilterContext  *ctx = inlink->dst;
460 460
     MixContext       *s = ctx->priv;
461 461
     AVFilterLink *outlink = ctx->outputs[0];
462
-    int i;
462
+    int i, ret = 0;
463 463
 
464 464
     for (i = 0; i < ctx->nb_inputs; i++)
465 465
         if (ctx->inputs[i] == inlink)
466 466
             break;
467 467
     if (i >= ctx->nb_inputs) {
468 468
         av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
469
-        return;
469
+        ret = AVERROR(EINVAL);
470
+        goto fail;
470 471
     }
471 472
 
472 473
     if (i == 0) {
473 474
         int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
474 475
                                    outlink->time_base);
475
-        frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts);
476
+        ret = frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts);
477
+        if (ret < 0)
478
+            goto fail;
476 479
     }
477 480
 
478
-    av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
479
-                        buf->audio->nb_samples);
481
+    ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
482
+                              buf->audio->nb_samples);
480 483
 
484
+fail:
481 485
     avfilter_unref_buffer(buf);
486
+
487
+    return ret;
482 488
 }
483 489
 
484 490
 static int init(AVFilterContext *ctx, const char *args)
... ...
@@ -136,18 +136,18 @@ static int request_frame(AVFilterLink *link)
136 136
         avresample_convert(s->avr, (void**)buf->extended_data, buf->linesize[0],
137 137
                            nb_samples, NULL, 0, 0);
138 138
         buf->pts = s->pts;
139
-        ff_filter_samples(link, buf);
140
-        return 0;
139
+        return ff_filter_samples(link, buf);
141 140
     }
142 141
 
143 142
     return ret;
144 143
 }
145 144
 
146
-static void write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf)
145
+static int write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf)
147 146
 {
148
-    avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
149
-                       buf->linesize[0], buf->audio->nb_samples);
147
+    int ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
148
+                                 buf->linesize[0], buf->audio->nb_samples);
150 149
     avfilter_unref_buffer(buf);
150
+    return ret;
151 151
 }
152 152
 
153 153
 /* get amount of data currently buffered, in samples */
... ...
@@ -156,7 +156,7 @@ static int64_t get_delay(ASyncContext *s)
156 156
     return avresample_available(s->avr) + avresample_get_delay(s->avr);
157 157
 }
158 158
 
159
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
159
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
160 160
 {
161 161
     AVFilterContext  *ctx = inlink->dst;
162 162
     ASyncContext       *s = ctx->priv;
... ...
@@ -164,7 +164,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
164 164
     int nb_channels = av_get_channel_layout_nb_channels(buf->audio->channel_layout);
165 165
     int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
166 166
                   av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
167
-    int out_size;
167
+    int out_size, ret;
168 168
     int64_t delta;
169 169
 
170 170
     /* buffer data until we get the first timestamp */
... ...
@@ -172,14 +172,12 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
172 172
         if (pts != AV_NOPTS_VALUE) {
173 173
             s->pts = pts - get_delay(s);
174 174
         }
175
-        write_to_fifo(s, buf);
176
-        return;
175
+        return write_to_fifo(s, buf);
177 176
     }
178 177
 
179 178
     /* now wait for the next timestamp */
180 179
     if (pts == AV_NOPTS_VALUE) {
181
-        write_to_fifo(s, buf);
182
-        return;
180
+        return write_to_fifo(s, buf);
183 181
     }
184 182
 
185 183
     /* when we have two timestamps, compute how many samples would we have
... ...
@@ -202,8 +200,10 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
202 202
     if (out_size > 0) {
203 203
         AVFilterBufferRef *buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
204 204
                                                          out_size);
205
-        if (!buf_out)
206
-            return;
205
+        if (!buf_out) {
206
+            ret = AVERROR(ENOMEM);
207
+            goto fail;
208
+        }
207 209
 
208 210
         avresample_read(s->avr, (void**)buf_out->extended_data, out_size);
209 211
         buf_out->pts = s->pts;
... ...
@@ -212,7 +212,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
212 212
             av_samples_set_silence(buf_out->extended_data, out_size - delta,
213 213
                                    delta, nb_channels, buf->format);
214 214
         }
215
-        ff_filter_samples(outlink, buf_out);
215
+        ret = ff_filter_samples(outlink, buf_out);
216
+        if (ret < 0)
217
+            goto fail;
216 218
         s->got_output = 1;
217 219
     } else {
218 220
         av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
... ...
@@ -223,9 +225,13 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
223 223
     avresample_read(s->avr, NULL, avresample_available(s->avr));
224 224
 
225 225
     s->pts = pts - avresample_get_delay(s->avr);
226
-    avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
227
-                       buf->linesize[0], buf->audio->nb_samples);
226
+    ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
227
+                             buf->linesize[0], buf->audio->nb_samples);
228
+
229
+fail:
228 230
     avfilter_unref_buffer(buf);
231
+
232
+    return ret;
229 233
 }
230 234
 
231 235
 AVFilter avfilter_af_asyncts = {
... ...
@@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx)
313 313
     return 0;
314 314
 }
315 315
 
316
-static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
316
+static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
317 317
 {
318 318
     AVFilterContext  *ctx = inlink->dst;
319 319
     AVFilterLink *outlink = ctx->outputs[0];
... ...
@@ -330,8 +330,10 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b
330 330
         if (nch_out > FF_ARRAY_ELEMS(buf->data)) {
331 331
             uint8_t **new_extended_data =
332 332
                 av_mallocz(nch_out * sizeof(*buf->extended_data));
333
-            if (!new_extended_data)
334
-                return;
333
+            if (!new_extended_data) {
334
+                avfilter_unref_buffer(buf);
335
+                return AVERROR(ENOMEM);
336
+            }
335 337
             if (buf->extended_data == buf->data) {
336 338
                 buf->extended_data = new_extended_data;
337 339
             } else {
... ...
@@ -353,7 +355,7 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b
353 353
         memcpy(buf->data, buf->extended_data,
354 354
            FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0]));
355 355
 
356
-    ff_filter_samples(outlink, buf);
356
+    return ff_filter_samples(outlink, buf);
357 357
 }
358 358
 
359 359
 static int channelmap_config_input(AVFilterLink *inlink)
... ...
@@ -110,24 +110,29 @@ static int query_formats(AVFilterContext *ctx)
110 110
     return 0;
111 111
 }
112 112
 
113
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
113
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
114 114
 {
115 115
     AVFilterContext *ctx = inlink->dst;
116
-    int i;
116
+    int i, ret = 0;
117 117
 
118 118
     for (i = 0; i < ctx->nb_outputs; i++) {
119 119
         AVFilterBufferRef *buf_out = avfilter_ref_buffer(buf, ~AV_PERM_WRITE);
120 120
 
121
-        if (!buf_out)
122
-            return;
121
+        if (!buf_out) {
122
+            ret = AVERROR(ENOMEM);
123
+            break;
124
+        }
123 125
 
124 126
         buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i];
125 127
         buf_out->audio->channel_layout =
126 128
             av_channel_layout_extract_channel(buf->audio->channel_layout, i);
127 129
 
128
-        ff_filter_samples(ctx->outputs[i], buf_out);
130
+        ret = ff_filter_samples(ctx->outputs[i], buf_out);
131
+        if (ret < 0)
132
+            break;
129 133
     }
130 134
     avfilter_unref_buffer(buf);
135
+    return ret;
131 136
 }
132 137
 
133 138
 AVFilter avfilter_af_channelsplit = {
... ...
@@ -92,7 +92,7 @@ static const AVClass join_class = {
92 92
     .version    = LIBAVUTIL_VERSION_INT,
93 93
 };
94 94
 
95
-static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
95
+static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
96 96
 {
97 97
     AVFilterContext *ctx = link->dst;
98 98
     JoinContext       *s = ctx->priv;
... ...
@@ -104,6 +104,8 @@ static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
104 104
     av_assert0(i < ctx->nb_inputs);
105 105
     av_assert0(!s->input_frames[i]);
106 106
     s->input_frames[i] = buf;
107
+
108
+    return 0;
107 109
 }
108 110
 
109 111
 static int parse_maps(AVFilterContext *ctx)
... ...
@@ -468,11 +470,11 @@ static int join_request_frame(AVFilterLink *outlink)
468 468
     priv->nb_in_buffers = ctx->nb_inputs;
469 469
     buf->buf->priv      = priv;
470 470
 
471
-    ff_filter_samples(outlink, buf);
471
+    ret = ff_filter_samples(outlink, buf);
472 472
 
473 473
     memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs);
474 474
 
475
-    return 0;
475
+    return ret;
476 476
 
477 477
 fail:
478 478
     avfilter_unref_buffer(buf);
... ...
@@ -157,21 +157,21 @@ static int request_frame(AVFilterLink *outlink)
157 157
         }
158 158
 
159 159
         buf->pts = s->next_pts;
160
-        ff_filter_samples(outlink, buf);
161
-        return 0;
160
+        return ff_filter_samples(outlink, buf);
162 161
     }
163 162
     return ret;
164 163
 }
165 164
 
166
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
165
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
167 166
 {
168 167
     AVFilterContext  *ctx = inlink->dst;
169 168
     ResampleContext    *s = ctx->priv;
170 169
     AVFilterLink *outlink = ctx->outputs[0];
170
+    int ret;
171 171
 
172 172
     if (s->avr) {
173 173
         AVFilterBufferRef *buf_out;
174
-        int delay, nb_samples, ret;
174
+        int delay, nb_samples;
175 175
 
176 176
         /* maximum possible samples lavr can output */
177 177
         delay      = avresample_get_delay(s->avr);
... ...
@@ -180,10 +180,19 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
180 180
                                     AV_ROUND_UP);
181 181
 
182 182
         buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
183
+        if (!buf_out) {
184
+            ret = AVERROR(ENOMEM);
185
+            goto fail;
186
+        }
187
+
183 188
         ret     = avresample_convert(s->avr, (void**)buf_out->extended_data,
184 189
                                      buf_out->linesize[0], nb_samples,
185 190
                                      (void**)buf->extended_data, buf->linesize[0],
186 191
                                      buf->audio->nb_samples);
192
+        if (ret < 0) {
193
+            avfilter_unref_buffer(buf_out);
194
+            goto fail;
195
+        }
187 196
 
188 197
         av_assert0(!avresample_available(s->avr));
189 198
 
... ...
@@ -209,14 +218,18 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
209 209
 
210 210
             s->next_pts = buf_out->pts + buf_out->audio->nb_samples;
211 211
 
212
-            ff_filter_samples(outlink, buf_out);
212
+            ret = ff_filter_samples(outlink, buf_out);
213 213
             s->got_output = 1;
214 214
         }
215
+
216
+fail:
215 217
         avfilter_unref_buffer(buf);
216 218
     } else {
217
-        ff_filter_samples(outlink, buf);
219
+        ret = ff_filter_samples(outlink, buf);
218 220
         s->got_output = 1;
219 221
     }
222
+
223
+    return ret;
220 224
 }
221 225
 
222 226
 AVFilter avfilter_af_resample = {
... ...
@@ -19,7 +19,10 @@
19 19
 #include "avfilter.h"
20 20
 #include "internal.h"
21 21
 
22
-static void null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { }
22
+static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
23
+{
24
+    return 0;
25
+}
23 26
 
24 27
 AVFilter avfilter_asink_anullsink = {
25 28
     .name        = "anullsink",
... ...
@@ -146,15 +146,15 @@ fail:
146 146
     return NULL;
147 147
 }
148 148
 
149
-static void default_filter_samples(AVFilterLink *link,
150
-                                   AVFilterBufferRef *samplesref)
149
+static int default_filter_samples(AVFilterLink *link,
150
+                                  AVFilterBufferRef *samplesref)
151 151
 {
152
-    ff_filter_samples(link->dst->outputs[0], samplesref);
152
+    return ff_filter_samples(link->dst->outputs[0], samplesref);
153 153
 }
154 154
 
155
-void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
155
+int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
156 156
 {
157
-    void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
157
+    int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
158 158
     AVFilterPad *dst = link->dstpad;
159 159
     AVFilterBufferRef *buf_out;
160 160
 
... ...
@@ -185,6 +185,6 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
185 185
     } else
186 186
         buf_out = samplesref;
187 187
 
188
-    filter_samples(link, buf_out);
188
+    return filter_samples(link, buf_out);
189 189
 }
190 190
 
... ...
@@ -49,7 +49,10 @@ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
49 49
  * @param samplesref a reference to the buffer of audio samples being sent. The
50 50
  *                   receiving filter will free this reference when it no longer
51 51
  *                   needs it or pass it on to the next filter.
52
+ *
53
+ * @return >= 0 on success, a negative AVERROR on error. The receiving filter
54
+ * is responsible for unreferencing samplesref in case of error.
52 55
  */
53
-void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
56
+int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
54 57
 
55 58
 #endif /* AVFILTER_AUDIO_H */
... ...
@@ -288,8 +288,12 @@ struct AVFilterPad {
288 288
      * and should do its processing.
289 289
      *
290 290
      * Input audio pads only.
291
+     *
292
+     * @return >= 0 on success, a negative AVERROR on error. This function
293
+     * must ensure that samplesref is properly unreferenced on error if it
294
+     * hasn't been passed on to another filter.
291 295
      */
292
-    void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
296
+    int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
293 297
 
294 298
     /**
295 299
      * Frame poll callback. This returns the number of immediately available
... ...
@@ -56,6 +56,12 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
56 56
     link->cur_buf = NULL;
57 57
 };
58 58
 
59
+static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
60
+{
61
+    start_frame(link, buf);
62
+    return 0;
63
+}
64
+
59 65
 int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
60 66
 {
61 67
     BufferSinkContext *s    = ctx->priv;
... ...
@@ -160,7 +166,7 @@ AVFilter avfilter_asink_abuffer = {
160 160
 
161 161
     .inputs    = (AVFilterPad[]) {{ .name           = "default",
162 162
                                     .type           = AVMEDIA_TYPE_AUDIO,
163
-                                    .filter_samples = start_frame,
163
+                                    .filter_samples = filter_samples,
164 164
                                     .min_perms      = AV_PERM_READ,
165 165
                                     .needs_fifo     = 1 },
166 166
                                   { .name = NULL }},
... ...
@@ -312,6 +312,7 @@ static int request_frame(AVFilterLink *link)
312 312
 {
313 313
     BufferSourceContext *c = link->src->priv;
314 314
     AVFilterBufferRef *buf;
315
+    int ret = 0;
315 316
 
316 317
     if (!av_fifo_size(c->fifo)) {
317 318
         if (c->eof)
... ...
@@ -327,7 +328,7 @@ static int request_frame(AVFilterLink *link)
327 327
         ff_end_frame(link);
328 328
         break;
329 329
     case AVMEDIA_TYPE_AUDIO:
330
-        ff_filter_samples(link, avfilter_ref_buffer(buf, ~0));
330
+        ret = ff_filter_samples(link, avfilter_ref_buffer(buf, ~0));
331 331
         break;
332 332
     default:
333 333
         return AVERROR(EINVAL);
... ...
@@ -335,7 +336,7 @@ static int request_frame(AVFilterLink *link)
335 335
 
336 336
     avfilter_unref_buffer(buf);
337 337
 
338
-    return 0;
338
+    return ret;
339 339
 }
340 340
 
341 341
 static int poll_frame(AVFilterLink *link)
... ...
@@ -72,13 +72,25 @@ static av_cold void uninit(AVFilterContext *ctx)
72 72
     avfilter_unref_buffer(fifo->buf_out);
73 73
 }
74 74
 
75
-static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
75
+static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
76 76
 {
77 77
     FifoContext *fifo = inlink->dst->priv;
78 78
 
79 79
     fifo->last->next = av_mallocz(sizeof(Buf));
80
+    if (!fifo->last->next) {
81
+        avfilter_unref_buffer(buf);
82
+        return AVERROR(ENOMEM);
83
+    }
84
+
80 85
     fifo->last = fifo->last->next;
81 86
     fifo->last->buf = buf;
87
+
88
+    return 0;
89
+}
90
+
91
+static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
92
+{
93
+    add_to_queue(inlink, buf);
82 94
 }
83 95
 
84 96
 static void queue_pop(FifoContext *s)
... ...
@@ -210,15 +222,13 @@ static int return_audio_frame(AVFilterContext *ctx)
210 210
         buf_out = s->buf_out;
211 211
         s->buf_out = NULL;
212 212
     }
213
-    ff_filter_samples(link, buf_out);
214
-
215
-    return 0;
213
+    return ff_filter_samples(link, buf_out);
216 214
 }
217 215
 
218 216
 static int request_frame(AVFilterLink *outlink)
219 217
 {
220 218
     FifoContext *fifo = outlink->src->priv;
221
-    int ret;
219
+    int ret = 0;
222 220
 
223 221
     if (!fifo->root.next) {
224 222
         if ((ret = ff_request_frame(outlink->src->inputs[0])) < 0)
... ...
@@ -238,7 +248,7 @@ static int request_frame(AVFilterLink *outlink)
238 238
         if (outlink->request_samples) {
239 239
             return return_audio_frame(outlink->src);
240 240
         } else {
241
-            ff_filter_samples(outlink, fifo->root.next->buf);
241
+            ret = ff_filter_samples(outlink, fifo->root.next->buf);
242 242
             queue_pop(fifo);
243 243
         }
244 244
         break;
... ...
@@ -246,7 +256,7 @@ static int request_frame(AVFilterLink *outlink)
246 246
         return AVERROR(EINVAL);
247 247
     }
248 248
 
249
-    return 0;
249
+    return ret;
250 250
 }
251 251
 
252 252
 AVFilter avfilter_vf_fifo = {
... ...
@@ -261,7 +271,7 @@ AVFilter avfilter_vf_fifo = {
261 261
     .inputs    = (AVFilterPad[]) {{ .name            = "default",
262 262
                                     .type            = AVMEDIA_TYPE_VIDEO,
263 263
                                     .get_video_buffer= ff_null_get_video_buffer,
264
-                                    .start_frame     = add_to_queue,
264
+                                    .start_frame     = start_frame,
265 265
                                     .draw_slice      = draw_slice,
266 266
                                     .end_frame       = end_frame,
267 267
                                     .rej_perms       = AV_PERM_REUSE2, },
... ...
@@ -111,8 +111,12 @@ struct AVFilterPad {
111 111
      * and should do its processing.
112 112
      *
113 113
      * Input audio pads only.
114
+     *
115
+     * @return >= 0 on success, a negative AVERROR on error. This function
116
+     * must ensure that samplesref is properly unreferenced on error if it
117
+     * hasn't been passed on to another filter.
114 118
      */
115
-    void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
119
+    int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
116 120
 
117 121
     /**
118 122
      * Frame poll callback. This returns the number of immediately available
... ...
@@ -110,15 +110,19 @@ AVFilter avfilter_vf_split = {
110 110
     .outputs   = (AVFilterPad[]) {{ .name = NULL}},
111 111
 };
112 112
 
113
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
113
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
114 114
 {
115 115
     AVFilterContext *ctx = inlink->dst;
116
-    int i;
116
+    int i, ret = 0;
117 117
 
118
-    for (i = 0; i < ctx->nb_outputs; i++)
119
-        ff_filter_samples(inlink->dst->outputs[i],
120
-                          avfilter_ref_buffer(samplesref, ~AV_PERM_WRITE));
118
+    for (i = 0; i < ctx->nb_outputs; i++) {
119
+        ret = ff_filter_samples(inlink->dst->outputs[i],
120
+                                avfilter_ref_buffer(samplesref, ~AV_PERM_WRITE));
121
+        if (ret < 0)
122
+            break;
123
+    }
121 124
     avfilter_unref_buffer(samplesref);
125
+    return ret;
122 126
 }
123 127
 
124 128
 AVFilter avfilter_af_asplit = {