Skip to content

Commit 32153fa

Browse files
committed
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. Signed-off-by: Marton Balint <[email protected]>
1 parent a21429e commit 32153fa

File tree

1 file changed

+34
-40
lines changed

1 file changed

+34
-40
lines changed

libavfilter/af_aresample.c

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ typedef struct AResampleContext {
4343
struct SwrContext *swr;
4444
int64_t next_pts;
4545
int more_data;
46-
int eof;
4746
} AResampleContext;
4847

4948
static av_cold int preinit(AVFilterContext *ctx)
@@ -209,7 +208,7 @@ static int config_output(AVFilterLink *outlink)
209208
return 0;
210209
}
211210

212-
static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
211+
static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref, AVFrame **outsamplesref_ret)
213212
{
214213
AVFilterContext *ctx = inlink->dst;
215214
AResampleContext *aresample = ctx->priv;
@@ -220,23 +219,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
220219
AVFrame *outsamplesref;
221220
int ret;
222221

222+
*outsamplesref_ret = NULL;
223223
delay = swr_get_delay(aresample->swr, outlink->sample_rate);
224224
if (delay > 0)
225225
n_out += FFMIN(delay, FFMAX(4096, n_out));
226226

227227
outsamplesref = ff_get_audio_buffer(outlink, n_out);
228-
229-
if(!outsamplesref) {
230-
av_frame_free(&insamplesref);
228+
if (!outsamplesref)
231229
return AVERROR(ENOMEM);
232-
}
233230

234231
av_frame_copy_props(outsamplesref, insamplesref);
235232
outsamplesref->format = outlink->format;
236233
ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout);
237234
if (ret < 0) {
238235
av_frame_free(&outsamplesref);
239-
av_frame_free(&insamplesref);
240236
return ret;
241237
}
242238
outsamplesref->sample_rate = outlink->sample_rate;
@@ -257,18 +253,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
257253
(void *)insamplesref->extended_data, n_in);
258254
if (n_out <= 0) {
259255
av_frame_free(&outsamplesref);
260-
av_frame_free(&insamplesref);
261-
ff_inlink_request_frame(inlink);
262256
return 0;
263257
}
264258

265259
aresample->more_data = outsamplesref->nb_samples == n_out; // Indicate that there is probably more data in our buffers
266260

267261
outsamplesref->nb_samples = n_out;
268262

269-
ret = ff_filter_frame(outlink, outsamplesref);
270-
av_frame_free(&insamplesref);
271-
return ret;
263+
*outsamplesref_ret = outsamplesref;
264+
return 1;
272265
}
273266

274267
static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret)
@@ -291,69 +284,70 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref
291284
n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0);
292285
if (n_out <= 0) {
293286
av_frame_free(&outsamplesref);
294-
return (n_out == 0) ? AVERROR_EOF : n_out;
287+
return n_out;
295288
}
296289

297290
outsamplesref->sample_rate = outlink->sample_rate;
298291
outsamplesref->nb_samples = n_out;
299292

300293
outsamplesref->pts = pts;
301294

302-
return 0;
295+
return 1;
303296
}
304297

305298
static int activate(AVFilterContext *ctx)
306299
{
307300
AVFilterLink *inlink = ctx->inputs[0];
308301
AVFilterLink *outlink = ctx->outputs[0];
309302
AResampleContext *aresample = ctx->priv;
303+
AVFrame *frame;
310304
int ret = 0, status;
311305
int64_t pts;
312306

313307
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
314308

315-
if (!aresample->eof && ff_inlink_queued_frames(inlink)) {
316-
AVFrame *frame = NULL;
309+
// First try to get data from the internal buffers
310+
if (aresample->more_data) {
311+
AVFrame *outsamplesref;
317312

318-
ret = ff_inlink_consume_frame(inlink, &frame);
313+
ret = flush_frame(outlink, 0, &outsamplesref);
319314
if (ret < 0)
320315
return ret;
321316
if (ret > 0)
322-
return filter_frame(inlink, frame);
317+
return ff_filter_frame(outlink, outsamplesref);
323318
}
319+
aresample->more_data = 0;
324320

325-
// First try to get data from the internal buffers
326-
if (aresample->more_data) {
321+
// Then consume frames from inlink
322+
while ((ret = ff_inlink_consume_frame(inlink, &frame))) {
327323
AVFrame *outsamplesref;
324+
if (ret < 0)
325+
return ret;
328326

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)
330332
return ff_filter_frame(outlink, outsamplesref);
331-
}
332333
}
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);
341334

342-
// Third if we hit the end flush
343-
if (aresample->eof) {
335+
// If we hit the end flush
336+
if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
344337
AVFrame *outsamplesref;
345338

346-
if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) {
347-
if (ret == AVERROR_EOF) {
348-
ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts);
349-
return 0;
350-
}
339+
ret = flush_frame(outlink, 1, &outsamplesref);
340+
if (ret < 0)
351341
return ret;
352-
}
353-
354-
return ff_filter_frame(outlink, outsamplesref);
342+
if (ret > 0)
343+
return ff_filter_frame(outlink, outsamplesref);
344+
ff_outlink_set_status(outlink, status, aresample->next_pts);
345+
return 0;
355346
}
356347

348+
// If not, request more data from the input
349+
FF_FILTER_FORWARD_WANTED(outlink, inlink);
350+
357351
return FFERROR_NOT_READY;
358352
}
359353

0 commit comments

Comments
 (0)