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
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) · 159 unmodified lines
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) · 4 unmodified lines
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,8 +253,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 14 unmodified lines
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
@@ -266,9 +260,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 1 unmodified line
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,7 +284,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 16 unmodified lines
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;
@@ -299,7 +292,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 1 unmodified line
299292
300293 outsamplesref->pts = pts;
301294
302− return 0;
295+ return 1;
303296 }
304297
305298 static int activate(AVFilterContext *ctx)
@@ -307,53 +300,54 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line
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

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