History

avfilter/af_aresample: rework activate logic to follow the advised flow more strictly

This should prevent the possibility of audio data accumulating. The commit also cleans up and simplifies the code a bit so all frame producers (filter_frame(), flush_frame()) functions follow similar logic as ff_inlink_consume_frame() for the return code.

Marton Balint committed 1 year ago

Commit 32153fa1 parent a21429e1 file · +34 −40Browse files

Unified · Split

libavfilter/af_aresample.c+34−40
@@ -43,7 +43,6 @@ typedef struct AResampleContext { · 42 unmodified lines
43 struct SwrContext *swr;43 struct SwrContext *swr;
44 int64_t next_pts;44 int64_t next_pts;
45 int more_data;45 int more_data;
46 int eof;
47} AResampleContext;46} AResampleContext;
48 47
49static av_cold int preinit(AVFilterContext *ctx)48static av_cold int preinit(AVFilterContext *ctx)
@@ -209,7 +208,7 @@ static int config_output(AVFilterLink *outlink) · 159 unmodified lines
209 return 0;208 return 0;
210}209}
211 210
212static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)211static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref, AVFrame **outsamplesref_ret)
213{212{
214 AVFilterContext *ctx = inlink->dst;213 AVFilterContext *ctx = inlink->dst;
215 AResampleContext *aresample = ctx->priv;214 AResampleContext *aresample = ctx->priv;
@@ -220,23 +219,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 4 unmodified lines
220 AVFrame *outsamplesref;219 AVFrame *outsamplesref;
221 int ret;220 int ret;
222 221
222 *outsamplesref_ret = NULL;
223 delay = swr_get_delay(aresample->swr, outlink->sample_rate);223 delay = swr_get_delay(aresample->swr, outlink->sample_rate);
224 if (delay > 0)224 if (delay > 0)
225 n_out += FFMIN(delay, FFMAX(4096, n_out));225 n_out += FFMIN(delay, FFMAX(4096, n_out));
226 226
227 outsamplesref = ff_get_audio_buffer(outlink, n_out);227 outsamplesref = ff_get_audio_buffer(outlink, n_out);
228 228 if (!outsamplesref)
229 if(!outsamplesref) {
230 av_frame_free(&insamplesref);
231 return AVERROR(ENOMEM);229 return AVERROR(ENOMEM);
232 }
233 230
234 av_frame_copy_props(outsamplesref, insamplesref);231 av_frame_copy_props(outsamplesref, insamplesref);
235 outsamplesref->format = outlink->format;232 outsamplesref->format = outlink->format;
236 ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout);233 ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout);
237 if (ret < 0) {234 if (ret < 0) {
238 av_frame_free(&outsamplesref);235 av_frame_free(&outsamplesref);
239 av_frame_free(&insamplesref);
240 return ret;236 return ret;
241 }237 }
242 outsamplesref->sample_rate = outlink->sample_rate;238 outsamplesref->sample_rate = outlink->sample_rate;
@@ -257,8 +253,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 14 unmodified lines
257 (void *)insamplesref->extended_data, n_in);253 (void *)insamplesref->extended_data, n_in);
258 if (n_out <= 0) {254 if (n_out <= 0) {
259 av_frame_free(&outsamplesref);255 av_frame_free(&outsamplesref);
260 av_frame_free(&insamplesref);
261 ff_inlink_request_frame(inlink);
262 return 0;256 return 0;
263 }257 }
264 258
@@ -266,9 +260,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 1 unmodified line
266 260
267 outsamplesref->nb_samples = n_out;261 outsamplesref->nb_samples = n_out;
268 262
269 ret = ff_filter_frame(outlink, outsamplesref);263 *outsamplesref_ret = outsamplesref;
270 av_frame_free(&insamplesref);264 return 1;
271 return ret;
272}265}
273 266
274static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret)267static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret)
@@ -291,7 +284,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 16 unmodified lines
291 n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0);284 n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0);
292 if (n_out <= 0) {285 if (n_out <= 0) {
293 av_frame_free(&outsamplesref);286 av_frame_free(&outsamplesref);
294 return (n_out == 0) ? AVERROR_EOF : n_out;287 return n_out;
295 }288 }
296 289
297 outsamplesref->sample_rate = outlink->sample_rate;290 outsamplesref->sample_rate = outlink->sample_rate;
@@ -299,7 +292,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 1 unmodified line
299 292
300 outsamplesref->pts = pts;293 outsamplesref->pts = pts;
301 294
302 return 0;295 return 1;
303}296}
304 297
305static int activate(AVFilterContext *ctx)298static int activate(AVFilterContext *ctx)
@@ -307,53 +300,54 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line
307 AVFilterLink *inlink = ctx->inputs[0];300 AVFilterLink *inlink = ctx->inputs[0];
308 AVFilterLink *outlink = ctx->outputs[0];301 AVFilterLink *outlink = ctx->outputs[0];
309 AResampleContext *aresample = ctx->priv;302 AResampleContext *aresample = ctx->priv;
303 AVFrame *frame;
310 int ret = 0, status;304 int ret = 0, status;
311 int64_t pts;305 int64_t pts;
312 306
313 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);307 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
314 308
315 if (!aresample->eof && ff_inlink_queued_frames(inlink)) {309 // First try to get data from the internal buffers
316 AVFrame *frame = NULL;310 if (aresample->more_data) {
311 AVFrame *outsamplesref;
317 312
318 ret = ff_inlink_consume_frame(inlink, &frame);313 ret = flush_frame(outlink, 0, &outsamplesref);
319 if (ret < 0)314 if (ret < 0)
320 return ret;315 return ret;
321 if (ret > 0)316 if (ret > 0)
322 return filter_frame(inlink, frame);317 return ff_filter_frame(outlink, outsamplesref);
323 }318 }
319 aresample->more_data = 0;
324 320
325 // First try to get data from the internal buffers321 // Then consume frames from inlink
326 if (aresample->more_data) {322 while ((ret = ff_inlink_consume_frame(inlink, &frame))) {
327 AVFrame *outsamplesref;323 AVFrame *outsamplesref;
324 if (ret < 0)
325 return ret;
328 326
329 if (flush_frame(outlink, 0, &outsamplesref) >= 0) {327 ret = filter_frame(inlink, frame, &outsamplesref);
328 av_frame_free(&frame);
329 if (ret < 0)
330 return ret;
331 if (ret > 0)
330 return ff_filter_frame(outlink, outsamplesref);332 return ff_filter_frame(outlink, outsamplesref);
331 }
332 }333 }
333 aresample->more_data = 0;
334
335 if (!aresample->eof && ff_inlink_acknowledge_status(inlink, &status, &pts))
336 aresample->eof = 1;
337
338 // Second request more data from the input
339 if (!aresample->eof)
340 FF_FILTER_FORWARD_WANTED(outlink, inlink);
341 334
342 // Third if we hit the end flush335 // If we hit the end flush
343 if (aresample->eof) {336 if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
344 AVFrame *outsamplesref;337 AVFrame *outsamplesref;
345 338
346 if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) {339 ret = flush_frame(outlink, 1, &outsamplesref);
347 if (ret == AVERROR_EOF) {340 if (ret < 0)
348 ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts);
349 return 0;
350 }
351 return ret;341 return ret;
352 }342 if (ret > 0)
353 343 return ff_filter_frame(outlink, outsamplesref);
354 return ff_filter_frame(outlink, outsamplesref);344 ff_outlink_set_status(outlink, status, aresample->next_pts);
345 return 0;
355 }346 }
356 347
348 // If not, request more data from the input
349 FF_FILTER_FORWARD_WANTED(outlink, inlink);
350
357 return FFERROR_NOT_READY;351 return FFERROR_NOT_READY;
358}352}
359 353

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t