... | ... |
@@ -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 = { |