Browse code

lavfi: make filter_frame non-recursive.

A lot of changes happen at the same time:

- Add a framequeue fifo to AVFilterLink.

- split AVFilterLink.status into status_in and status_out: requires
changes to the few filters and programs that use it directly
(f_interleave, split, filtfmts).

- Add a field ready to AVFilterContext, marking when the filter is ready
and its activation priority.

- Add flags to mark blocked links.

- Change ff_filter_frame() to enqueue the frame.

- Change all filtering functions to update the ready field and the
blocked flags.

- Update ff_filter_graph_run_once() to use the ready field.

- buffersrc: always push the frame immediately.

Nicolas George authored on 2016/01/03 23:44:42
Showing 10 changed files
... ...
@@ -34,6 +34,9 @@
34 34
 #include "libavutil/rational.h"
35 35
 #include "libavutil/samplefmt.h"
36 36
 
37
+#define FF_INTERNAL_FIELDS 1
38
+#include "framequeue.h"
39
+
37 40
 #include "audio.h"
38 41
 #include "avfilter.h"
39 42
 #include "formats.h"
... ...
@@ -135,6 +138,10 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
135 135
 {
136 136
     AVFilterLink *link;
137 137
 
138
+    av_assert0(src->graph);
139
+    av_assert0(dst->graph);
140
+    av_assert0(src->graph == dst->graph);
141
+
138 142
     if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad ||
139 143
         src->outputs[srcpad]      || dst->inputs[dstpad])
140 144
         return AVERROR(EINVAL);
... ...
@@ -160,6 +167,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
160 160
     link->type    = src->output_pads[srcpad].type;
161 161
     av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
162 162
     link->format  = -1;
163
+    ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
163 164
 
164 165
     return 0;
165 166
 }
... ...
@@ -170,6 +178,7 @@ void avfilter_link_free(AVFilterLink **link)
170 170
         return;
171 171
 
172 172
     av_frame_free(&(*link)->partial_buf);
173
+    ff_framequeue_free(&(*link)->fifo);
173 174
     ff_video_frame_pool_uninit((FFVideoFramePool**)&(*link)->video_frame_pool);
174 175
 
175 176
     av_freep(link);
... ...
@@ -180,16 +189,46 @@ int avfilter_link_get_channels(AVFilterLink *link)
180 180
     return link->channels;
181 181
 }
182 182
 
183
+static void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
184
+{
185
+    filter->ready = FFMAX(filter->ready, priority);
186
+}
187
+
188
+/**
189
+ * Clear frame_blocked_in on all outputs.
190
+ * This is necessary whenever something changes on input.
191
+ */
192
+static void filter_unblock(AVFilterContext *filter)
193
+{
194
+    unsigned i;
195
+
196
+    for (i = 0; i < filter->nb_outputs; i++)
197
+        filter->outputs[i]->frame_blocked_in = 0;
198
+}
199
+
200
+
183 201
 void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
184 202
 {
185
-    ff_avfilter_link_set_out_status(link, status, pts);
203
+    if (link->status_in == status)
204
+        return;
205
+    av_assert0(!link->status_in);
206
+    link->status_in = status;
207
+    link->status_in_pts = pts;
208
+    link->frame_wanted_out = 0;
209
+    link->frame_blocked_in = 0;
210
+    filter_unblock(link->dst);
211
+    ff_filter_set_ready(link->dst, 200);
186 212
 }
187 213
 
188 214
 void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
189 215
 {
190
-    link->status = status;
191
-    link->frame_wanted_in = link->frame_wanted_out = 0;
192
-    ff_update_link_current_pts(link, pts);
216
+    av_assert0(!link->frame_wanted_out);
217
+    av_assert0(!link->status_out);
218
+    link->status_out = status;
219
+    if (pts != AV_NOPTS_VALUE)
220
+        ff_update_link_current_pts(link, pts);
221
+    filter_unblock(link->dst);
222
+    ff_filter_set_ready(link->src, 200);
193 223
 }
194 224
 
195 225
 void avfilter_link_set_closed(AVFilterLink *link, int closed)
... ...
@@ -370,10 +409,23 @@ int ff_request_frame(AVFilterLink *link)
370 370
 {
371 371
     FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
372 372
 
373
-    if (link->status)
374
-        return link->status;
375
-    link->frame_wanted_in = 1;
373
+    if (link->status_out)
374
+        return link->status_out;
375
+    if (link->status_in) {
376
+        if (ff_framequeue_queued_frames(&link->fifo)) {
377
+            av_assert1(!link->frame_wanted_out);
378
+            av_assert1(link->dst->ready >= 300);
379
+            return 0;
380
+        } else {
381
+            /* Acknowledge status change. Filters using ff_request_frame() will
382
+               handle the change automatically. Filters can also check the
383
+               status directly but none do yet. */
384
+            ff_avfilter_link_set_out_status(link, link->status_in, link->status_in_pts);
385
+            return link->status_out;
386
+        }
387
+    }
376 388
     link->frame_wanted_out = 1;
389
+    ff_filter_set_ready(link->src, 100);
377 390
     return 0;
378 391
 }
379 392
 
... ...
@@ -382,22 +434,17 @@ int ff_request_frame_to_filter(AVFilterLink *link)
382 382
     int ret = -1;
383 383
 
384 384
     FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1);
385
-    link->frame_wanted_in = 0;
385
+    /* Assume the filter is blocked, let the method clear it if not */
386
+    link->frame_blocked_in = 1;
386 387
     if (link->srcpad->request_frame)
387 388
         ret = link->srcpad->request_frame(link);
388 389
     else if (link->src->inputs[0])
389 390
         ret = ff_request_frame(link->src->inputs[0]);
390
-    if (ret == AVERROR_EOF && link->partial_buf) {
391
-        AVFrame *pbuf = link->partial_buf;
392
-        link->partial_buf = NULL;
393
-        ret = ff_filter_frame_framed(link, pbuf);
394
-        ff_avfilter_link_set_in_status(link, AVERROR_EOF, AV_NOPTS_VALUE);
395
-        link->frame_wanted_out = 0;
396
-        return ret;
397
-    }
398 391
     if (ret < 0) {
399
-        if (ret != AVERROR(EAGAIN) && ret != link->status)
392
+        if (ret != AVERROR(EAGAIN) && ret != link->status_in)
400 393
             ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE);
394
+        if (ret == AVERROR_EOF)
395
+            ret = 0;
401 396
     }
402 397
     return ret;
403 398
 }
... ...
@@ -1056,11 +1103,6 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
1056 1056
     AVFilterCommand *cmd= link->dst->command_queue;
1057 1057
     int64_t pts;
1058 1058
 
1059
-    if (link->status) {
1060
-        av_frame_free(&frame);
1061
-        return link->status;
1062
-    }
1063
-
1064 1059
     if (!(filter_frame = dst->filter_frame))
1065 1060
         filter_frame = default_filter_frame;
1066 1061
 
... ...
@@ -1142,52 +1184,9 @@ fail:
1142 1142
     return ret;
1143 1143
 }
1144 1144
 
1145
-static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame)
1146
-{
1147
-    int insamples = frame->nb_samples, inpos = 0, nb_samples;
1148
-    AVFrame *pbuf = link->partial_buf;
1149
-    int nb_channels = av_frame_get_channels(frame);
1150
-    int ret = 0;
1151
-
1152
-    /* Handle framing (min_samples, max_samples) */
1153
-    while (insamples) {
1154
-        if (!pbuf) {
1155
-            AVRational samples_tb = { 1, link->sample_rate };
1156
-            pbuf = ff_get_audio_buffer(link, link->partial_buf_size);
1157
-            if (!pbuf) {
1158
-                av_log(link->dst, AV_LOG_WARNING,
1159
-                       "Samples dropped due to memory allocation failure.\n");
1160
-                return 0;
1161
-            }
1162
-            av_frame_copy_props(pbuf, frame);
1163
-            pbuf->pts = frame->pts;
1164
-            if (pbuf->pts != AV_NOPTS_VALUE)
1165
-                pbuf->pts += av_rescale_q(inpos, samples_tb, link->time_base);
1166
-            pbuf->nb_samples = 0;
1167
-        }
1168
-        nb_samples = FFMIN(insamples,
1169
-                           link->partial_buf_size - pbuf->nb_samples);
1170
-        av_samples_copy(pbuf->extended_data, frame->extended_data,
1171
-                        pbuf->nb_samples, inpos,
1172
-                        nb_samples, nb_channels, link->format);
1173
-        inpos                   += nb_samples;
1174
-        insamples               -= nb_samples;
1175
-        pbuf->nb_samples += nb_samples;
1176
-        if (pbuf->nb_samples >= link->min_samples) {
1177
-            ret = ff_filter_frame_framed(link, pbuf);
1178
-            pbuf = NULL;
1179
-        } else {
1180
-            if (link->frame_wanted_out)
1181
-                link->frame_wanted_in = 1;
1182
-        }
1183
-    }
1184
-    av_frame_free(&frame);
1185
-    link->partial_buf = pbuf;
1186
-    return ret;
1187
-}
1188
-
1189 1145
 int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
1190 1146
 {
1147
+    int ret;
1191 1148
     FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
1192 1149
 
1193 1150
     /* Consistency checks */
... ...
@@ -1220,23 +1219,329 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
1220 1220
         }
1221 1221
     }
1222 1222
 
1223
-    link->frame_wanted_out = 0;
1223
+    link->frame_blocked_in = link->frame_wanted_out = 0;
1224 1224
     link->frame_count_in++;
1225
-    /* Go directly to actual filtering if possible */
1226
-    if (link->type == AVMEDIA_TYPE_AUDIO &&
1227
-        link->min_samples &&
1228
-        (link->partial_buf ||
1229
-         frame->nb_samples < link->min_samples ||
1230
-         frame->nb_samples > link->max_samples)) {
1231
-        return ff_filter_frame_needs_framing(link, frame);
1232
-    } else {
1233
-        return ff_filter_frame_framed(link, frame);
1225
+    filter_unblock(link->dst);
1226
+    ret = ff_framequeue_add(&link->fifo, frame);
1227
+    if (ret < 0) {
1228
+        av_frame_free(&frame);
1229
+        return ret;
1234 1230
     }
1231
+    ff_filter_set_ready(link->dst, 300);
1232
+    return 0;
1233
+
1235 1234
 error:
1236 1235
     av_frame_free(&frame);
1237 1236
     return AVERROR_PATCHWELCOME;
1238 1237
 }
1239 1238
 
1239
+static int samples_ready(AVFilterLink *link)
1240
+{
1241
+    return ff_framequeue_queued_frames(&link->fifo) &&
1242
+           (ff_framequeue_queued_samples(&link->fifo) >= link->min_samples ||
1243
+            link->status_in);
1244
+}
1245
+
1246
+static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
1247
+                        AVFrame **rframe)
1248
+{
1249
+    AVFrame *frame0, *frame, *buf;
1250
+    unsigned nb_samples, nb_frames, i, p;
1251
+    int ret;
1252
+
1253
+    /* Note: this function relies on no format changes and must only be
1254
+       called with enough samples. */
1255
+    av_assert1(samples_ready(link));
1256
+    frame0 = frame = ff_framequeue_peek(&link->fifo, 0);
1257
+    if (frame->nb_samples >= min && frame->nb_samples < max) {
1258
+        *rframe = ff_framequeue_take(&link->fifo);
1259
+        return 0;
1260
+    }
1261
+    nb_frames = 0;
1262
+    nb_samples = 0;
1263
+    while (1) {
1264
+        if (nb_samples + frame->nb_samples > max) {
1265
+            if (nb_samples < min)
1266
+                nb_samples = max;
1267
+            break;
1268
+        }
1269
+        nb_samples += frame->nb_samples;
1270
+        nb_frames++;
1271
+        if (nb_frames == ff_framequeue_queued_frames(&link->fifo))
1272
+            break;
1273
+        frame = ff_framequeue_peek(&link->fifo, nb_frames);
1274
+    }
1275
+
1276
+    buf = ff_get_audio_buffer(link, nb_samples);
1277
+    if (!buf)
1278
+        return AVERROR(ENOMEM);
1279
+    ret = av_frame_copy_props(buf, frame0);
1280
+    if (ret < 0) {
1281
+        av_frame_free(&buf);
1282
+        return ret;
1283
+    }
1284
+    buf->pts = frame0->pts;
1285
+
1286
+    p = 0;
1287
+    for (i = 0; i < nb_frames; i++) {
1288
+        frame = ff_framequeue_take(&link->fifo);
1289
+        av_samples_copy(buf->extended_data, frame->extended_data, p, 0,
1290
+                        frame->nb_samples, link->channels, link->format);
1291
+        p += frame->nb_samples;
1292
+    }
1293
+    if (p < nb_samples) {
1294
+        unsigned n = nb_samples - p;
1295
+        frame = ff_framequeue_peek(&link->fifo, 0);
1296
+        av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
1297
+                        link->channels, link->format);
1298
+        frame->nb_samples -= n;
1299
+        av_samples_copy(frame->extended_data, frame->extended_data, 0, n,
1300
+                        frame->nb_samples, link->channels, link->format);
1301
+        if (frame->pts != AV_NOPTS_VALUE)
1302
+            frame->pts += av_rescale_q(n, av_make_q(1, link->sample_rate), link->time_base);
1303
+        ff_framequeue_update_peeked(&link->fifo, 0);
1304
+        ff_framequeue_skip_samples(&link->fifo, n);
1305
+    }
1306
+
1307
+    *rframe = buf;
1308
+    return 0;
1309
+}
1310
+
1311
+int ff_filter_frame_to_filter(AVFilterLink *link)
1312
+{
1313
+    AVFrame *frame;
1314
+    AVFilterContext *dst = link->dst;
1315
+    int ret;
1316
+
1317
+    av_assert1(ff_framequeue_queued_frames(&link->fifo));
1318
+    if (link->min_samples) {
1319
+        int min = link->min_samples;
1320
+        if (link->status_in)
1321
+            min = FFMIN(min, ff_framequeue_queued_samples(&link->fifo));
1322
+        ret = take_samples(link, min, link->max_samples, &frame);
1323
+        if (ret < 0)
1324
+            return ret;
1325
+    } else {
1326
+        frame = ff_framequeue_take(&link->fifo);
1327
+    }
1328
+    /* The filter will soon have received a new frame, that may allow it to
1329
+       produce one or more: unblock its outputs. */
1330
+    filter_unblock(dst);
1331
+    ret = ff_filter_frame_framed(link, frame);
1332
+    if (ret < 0 && ret != link->status_out) {
1333
+        ff_avfilter_link_set_out_status(link, ret, AV_NOPTS_VALUE);
1334
+    } else {
1335
+        /* Run once again, to see if several frames were available, or if
1336
+           the input status has also changed, or any other reason. */
1337
+        ff_filter_set_ready(dst, 300);
1338
+    }
1339
+    return ret;
1340
+}
1341
+
1342
+static int forward_status_change(AVFilterContext *filter, AVFilterLink *in)
1343
+{
1344
+    unsigned out = 0, progress = 0;
1345
+    int ret;
1346
+
1347
+    av_assert0(!in->status_out);
1348
+    if (!filter->nb_outputs) {
1349
+        /* not necessary with the current API and sinks */
1350
+        return 0;
1351
+    }
1352
+    while (!in->status_out) {
1353
+        if (!filter->outputs[out]->status_in) {
1354
+            progress++;
1355
+            ret = ff_request_frame_to_filter(filter->outputs[out]);
1356
+            if (ret < 0)
1357
+                return ret;
1358
+        }
1359
+        if (++out == filter->nb_outputs) {
1360
+            if (!progress) {
1361
+                /* Every output already closed: input no longer interesting
1362
+                   (example: overlay in shortest mode, other input closed). */
1363
+                ff_avfilter_link_set_out_status(in, in->status_in, in->status_in_pts);
1364
+                return 0;
1365
+            }
1366
+            progress = 0;
1367
+            out = 0;
1368
+        }
1369
+    }
1370
+    ff_filter_set_ready(filter, 200);
1371
+    return 0;
1372
+}
1373
+
1374
+#define FFERROR_NOT_READY FFERRTAG('N','R','D','Y')
1375
+
1376
+static int ff_filter_activate_default(AVFilterContext *filter)
1377
+{
1378
+    unsigned i;
1379
+
1380
+    for (i = 0; i < filter->nb_inputs; i++) {
1381
+        if (samples_ready(filter->inputs[i])) {
1382
+            return ff_filter_frame_to_filter(filter->inputs[i]);
1383
+        }
1384
+    }
1385
+    for (i = 0; i < filter->nb_inputs; i++) {
1386
+        if (filter->inputs[i]->status_in && !filter->inputs[i]->status_out) {
1387
+            av_assert1(!ff_framequeue_queued_frames(&filter->inputs[i]->fifo));
1388
+            return forward_status_change(filter, filter->inputs[i]);
1389
+        }
1390
+    }
1391
+    for (i = 0; i < filter->nb_outputs; i++) {
1392
+        if (filter->outputs[i]->frame_wanted_out &&
1393
+            !filter->outputs[i]->frame_blocked_in) {
1394
+            return ff_request_frame_to_filter(filter->outputs[i]);
1395
+        }
1396
+    }
1397
+    return FFERROR_NOT_READY;
1398
+}
1399
+
1400
+/*
1401
+   Filter scheduling and activation
1402
+
1403
+   When a filter is activated, it must:
1404
+   - if possible, output a frame;
1405
+   - else, if relevant, forward the input status change;
1406
+   - else, check outputs for wanted frames and forward the requests.
1407
+
1408
+   The following AVFilterLink fields are used for activation:
1409
+
1410
+   - frame_wanted_out:
1411
+
1412
+     This field indicates if a frame is needed on this input of the
1413
+     destination filter. A positive value indicates that a frame is needed
1414
+     to process queued frames or internal data or to satisfy the
1415
+     application; a zero value indicates that a frame is not especially
1416
+     needed but could be processed anyway; a negative value indicates that a
1417
+     frame would just be queued.
1418
+
1419
+     It is set by filters using ff_request_frame() or ff_request_no_frame(),
1420
+     when requested by the application through a specific API or when it is
1421
+     set on one of the outputs.
1422
+
1423
+     It is cleared when a frame is sent from the source using
1424
+     ff_filter_frame().
1425
+
1426
+     It is also cleared when a status change is sent from the source using
1427
+     ff_avfilter_link_set_in_status().
1428
+
1429
+   - frame_blocked_in:
1430
+
1431
+     This field means that the source filter can not generate a frame as is.
1432
+     Its goal is to avoid repeatedly calling the request_frame() method on
1433
+     the same link.
1434
+
1435
+     It is set by the framework on all outputs of a filter before activating it.
1436
+
1437
+     It is automatically cleared by ff_filter_frame().
1438
+
1439
+     It is also automatically cleared by ff_avfilter_link_set_in_status().
1440
+
1441
+     It is also cleared on all outputs (using filter_unblock()) when
1442
+     something happens on an input: processing a frame or changing the
1443
+     status.
1444
+
1445
+   - fifo:
1446
+
1447
+     Contains the frames queued on a filter input. If it contains frames and
1448
+     frame_wanted_out is not set, then the filter can be activated. If that
1449
+     result in the filter not able to use these frames, the filter must set
1450
+     frame_wanted_out to ask for more frames.
1451
+
1452
+   - status_in and status_in_pts:
1453
+
1454
+     Status (EOF or error code) of the link and timestamp of the status
1455
+     change (in link time base, same as frames) as seen from the input of
1456
+     the link. The status change is considered happening after the frames
1457
+     queued in fifo.
1458
+
1459
+     It is set by the source filter using ff_avfilter_link_set_in_status().
1460
+
1461
+   - status_out:
1462
+
1463
+     Status of the link as seen from the output of the link. The status
1464
+     change is considered having already happened.
1465
+
1466
+     It is set by the destination filter using
1467
+     ff_avfilter_link_set_out_status().
1468
+
1469
+   Filters are activated according to the ready field, set using the
1470
+   ff_filter_set_ready(). Eventually, a priority queue will be used.
1471
+   ff_filter_set_ready() is called whenever anything could cause progress to
1472
+   be possible. Marking a filter ready when it is not is not a problem,
1473
+   except for the small overhead it causes.
1474
+
1475
+   Conditions that cause a filter to be marked ready are:
1476
+
1477
+   - frames added on an input link;
1478
+
1479
+   - changes in the input or output status of an input link;
1480
+
1481
+   - requests for a frame on an output link;
1482
+
1483
+   - after any actual processing using the legacy methods (filter_frame(),
1484
+     and request_frame() to acknowledge status changes), to run once more
1485
+     and check if enough input was present for several frames.
1486
+
1487
+   Exemples of scenarios to consider:
1488
+
1489
+   - buffersrc: activate if frame_wanted_out to notify the application;
1490
+     activate when the application adds a frame to push it immediately.
1491
+
1492
+   - testsrc: activate only if frame_wanted_out to produce and push a frame.
1493
+
1494
+   - concat (not at stitch points): can process a frame on any output.
1495
+     Activate if frame_wanted_out on output to forward on the corresponding
1496
+     input. Activate when a frame is present on input to process it
1497
+     immediately.
1498
+
1499
+   - framesync: needs at least one frame on each input; extra frames on the
1500
+     wrong input will accumulate. When a frame is first added on one input,
1501
+     set frame_wanted_out<0 on it to avoid getting more (would trigger
1502
+     testsrc) and frame_wanted_out>0 on the other to allow processing it.
1503
+
1504
+   Activation of old filters:
1505
+
1506
+   In order to activate a filter implementing the legacy filter_frame() and
1507
+   request_frame() methods, perform the first possible of the following
1508
+   actions:
1509
+
1510
+   - If an input has frames in fifo and frame_wanted_out == 0, dequeue a
1511
+     frame and call filter_frame().
1512
+
1513
+     Ratinale: filter frames as soon as possible instead of leaving them
1514
+     queued; frame_wanted_out < 0 is not possible since the old API does not
1515
+     set it nor provides any similar feedback; frame_wanted_out > 0 happens
1516
+     when min_samples > 0 and there are not enough samples queued.
1517
+
1518
+   - If an input has status_in set but not status_out, try to call
1519
+     request_frame() on one of the outputs in the hope that it will trigger
1520
+     request_frame() on the input with status_in and acknowledge it. This is
1521
+     awkward and fragile, filters with several inputs or outputs should be
1522
+     updated to direct activation as soon as possible.
1523
+
1524
+   - If an output has frame_wanted_out > 0 and not frame_blocked_in, call
1525
+     request_frame().
1526
+
1527
+     Rationale: checking frame_blocked_in is necessary to avoid requesting
1528
+     repeatedly on a blocked input if another is not blocked (example:
1529
+     [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2).
1530
+
1531
+     TODO: respect needs_fifo and remove auto-inserted fifos.
1532
+
1533
+ */
1534
+
1535
+int ff_filter_activate(AVFilterContext *filter)
1536
+{
1537
+    int ret;
1538
+
1539
+    filter->ready = 0;
1540
+    ret = ff_filter_activate_default(filter);
1541
+    if (ret == FFERROR_NOT_READY)
1542
+        ret = 0;
1543
+    return ret;
1544
+}
1545
+
1240 1546
 const AVClass *avfilter_get_class(void)
1241 1547
 {
1242 1548
     return &avfilter_class;
... ...
@@ -368,6 +368,13 @@ struct AVFilterContext {
368 368
      * Overrides global number of threads set per filter graph.
369 369
      */
370 370
     int nb_threads;
371
+
372
+    /**
373
+     * Ready status of the filter.
374
+     * A non-0 value means that the filter needs activating;
375
+     * a higher value suggests a more urgent activation.
376
+     */
377
+    unsigned ready;
371 378
 };
372 379
 
373 380
 /**
... ...
@@ -509,18 +516,6 @@ struct AVFilterLink {
509 509
     int max_samples;
510 510
 
511 511
     /**
512
-     * Link status.
513
-     * If not zero, all attempts of filter_frame or request_frame
514
-     * will fail with the corresponding code, and if necessary the reference
515
-     * will be destroyed.
516
-     * If request_frame returns an error, the status is set on the
517
-     * corresponding link.
518
-     * It can be set also be set by either the source or the destination
519
-     * filter.
520
-     */
521
-    int status;
522
-
523
-    /**
524 512
      * Number of channels.
525 513
      */
526 514
     int channels;
... ...
@@ -541,13 +536,6 @@ struct AVFilterLink {
541 541
     void *video_frame_pool;
542 542
 
543 543
     /**
544
-     * True if a frame is currently wanted on the input of this filter.
545
-     * Set when ff_request_frame() is called by the output,
546
-     * cleared when the request is handled or forwarded.
547
-     */
548
-    int frame_wanted_in;
549
-
550
-    /**
551 544
      * True if a frame is currently wanted on the output of this filter.
552 545
      * Set when ff_request_frame() is called by the output,
553 546
      * cleared when a frame is filtered.
... ...
@@ -559,6 +547,51 @@ struct AVFilterLink {
559 559
      * AVHWFramesContext describing the frames.
560 560
      */
561 561
     AVBufferRef *hw_frames_ctx;
562
+
563
+#ifndef FF_INTERNAL_FIELDS
564
+
565
+    /**
566
+     * Internal structure members.
567
+     * The fields below this limit are internal for libavfilter's use
568
+     * and must in no way be accessed by applications.
569
+     */
570
+    char reserved[0xF000];
571
+
572
+#else /* FF_INTERNAL_FIELDS */
573
+
574
+    /**
575
+     * Queue of frames waiting to be filtered.
576
+     */
577
+    FFFrameQueue fifo;
578
+
579
+    /**
580
+     * If set, the source filter can not generate a frame as is.
581
+     * The goal is to avoid repeatedly calling the request_frame() method on
582
+     * the same link.
583
+     */
584
+    int frame_blocked_in;
585
+
586
+    /**
587
+     * Link input status.
588
+     * If not zero, all attempts of filter_frame will fail with the
589
+     * corresponding code.
590
+     */
591
+    int status_in;
592
+
593
+    /**
594
+     * Timestamp of the input status change.
595
+     */
596
+    int64_t status_in_pts;
597
+
598
+    /**
599
+     * Link output status.
600
+     * If not zero, all attempts of request_frame will fail with the
601
+     * corresponding code.
602
+     */
603
+    int status_out;
604
+
605
+#endif /* FF_INTERNAL_FIELDS */
606
+
562 607
 };
563 608
 
564 609
 /**
... ...
@@ -32,6 +32,9 @@
32 32
 #include "libavutil/opt.h"
33 33
 #include "libavutil/pixdesc.h"
34 34
 
35
+#define FF_INTERNAL_FIELDS 1
36
+#include "framequeue.h"
37
+
35 38
 #include "avfilter.h"
36 39
 #include "formats.h"
37 40
 #include "internal.h"
... ...
@@ -87,6 +90,7 @@ AVFilterGraph *avfilter_graph_alloc(void)
87 87
 
88 88
     ret->av_class = &filtergraph_class;
89 89
     av_opt_set_defaults(ret);
90
+    ff_framequeue_global_init(&ret->internal->frame_queues);
90 91
 
91 92
     return ret;
92 93
 }
... ...
@@ -1377,10 +1381,10 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
1377 1377
     heap_bubble_down(graph, link, link->age_index);
1378 1378
 }
1379 1379
 
1380
-
1381 1380
 int avfilter_graph_request_oldest(AVFilterGraph *graph)
1382 1381
 {
1383 1382
     AVFilterLink *oldest = graph->sink_links[0];
1383
+    int64_t frame_count;
1384 1384
     int r;
1385 1385
 
1386 1386
     while (graph->sink_links_count) {
... ...
@@ -1400,7 +1404,8 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
1400 1400
     if (!graph->sink_links_count)
1401 1401
         return AVERROR_EOF;
1402 1402
     av_assert1(oldest->age_index >= 0);
1403
-    while (oldest->frame_wanted_out) {
1403
+    frame_count = oldest->frame_count_out;
1404
+    while (frame_count == oldest->frame_count_out) {
1404 1405
         r = ff_filter_graph_run_once(graph);
1405 1406
         if (r < 0)
1406 1407
             return r;
... ...
@@ -1408,41 +1413,17 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
1408 1408
     return 0;
1409 1409
 }
1410 1410
 
1411
-static AVFilterLink *graph_run_once_find_filter(AVFilterGraph *graph)
1412
-{
1413
-    unsigned i, j;
1414
-    AVFilterContext *f;
1415
-
1416
-    /* TODO: replace scanning the graph with a priority list */
1417
-    for (i = 0; i < graph->nb_filters; i++) {
1418
-        f = graph->filters[i];
1419
-        for (j = 0; j < f->nb_outputs; j++)
1420
-            if (f->outputs[j]->frame_wanted_in)
1421
-                return f->outputs[j];
1422
-    }
1423
-    for (i = 0; i < graph->nb_filters; i++) {
1424
-        f = graph->filters[i];
1425
-        for (j = 0; j < f->nb_outputs; j++)
1426
-            if (f->outputs[j]->frame_wanted_out)
1427
-                return f->outputs[j];
1428
-    }
1429
-    return NULL;
1430
-}
1431
-
1432 1411
 int ff_filter_graph_run_once(AVFilterGraph *graph)
1433 1412
 {
1434
-    AVFilterLink *link;
1435
-    int ret;
1436
-
1437
-    link = graph_run_once_find_filter(graph);
1438
-    if (!link) {
1439
-        av_log(NULL, AV_LOG_WARNING, "Useless run of a filter graph\n");
1413
+    AVFilterContext *filter;
1414
+    unsigned i;
1415
+
1416
+    av_assert0(graph->nb_filters);
1417
+    filter = graph->filters[0];
1418
+    for (i = 1; i < graph->nb_filters; i++)
1419
+        if (graph->filters[i]->ready > filter->ready)
1420
+            filter = graph->filters[i];
1421
+    if (!filter->ready)
1440 1422
         return AVERROR(EAGAIN);
1441
-    }
1442
-    ret = ff_request_frame_to_filter(link);
1443
-    if (ret == AVERROR_EOF)
1444
-        /* local EOF will be forwarded through request_frame() /
1445
-           set_status() until it reaches the sink */
1446
-        ret = 0;
1447
-    return ret < 0 ? ret : 1;
1423
+    return ff_filter_activate(filter);
1448 1424
 }
... ...
@@ -31,6 +31,9 @@
31 31
 #include "libavutil/mathematics.h"
32 32
 #include "libavutil/opt.h"
33 33
 
34
+#define FF_INTERNAL_FIELDS 1
35
+#include "framequeue.h"
36
+
34 37
 #include "audio.h"
35 38
 #include "avfilter.h"
36 39
 #include "buffersink.h"
... ...
@@ -129,18 +132,26 @@ int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFr
129 129
 {
130 130
     BufferSinkContext *buf = ctx->priv;
131 131
     AVFilterLink *inlink = ctx->inputs[0];
132
-    int ret;
132
+    int peek_in_framequeue = 0, ret;
133
+    int64_t frame_count;
133 134
     AVFrame *cur_frame;
134 135
 
135 136
     /* no picref available, fetch it from the filterchain */
136 137
     while (!av_fifo_size(buf->fifo)) {
137
-        if (inlink->status)
138
-            return inlink->status;
139
-        if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
138
+        /* if peek_in_framequeue is true later, then ff_request_frame() and
139
+           the ff_filter_graph_run_once() loop will take a frame from it and
140
+           move it to the internal fifo, ending the global loop */
141
+        av_assert0(!peek_in_framequeue);
142
+        if (inlink->status_out)
143
+            return inlink->status_out;
144
+        peek_in_framequeue = ff_framequeue_queued_frames(&inlink->fifo) &&
145
+                             ff_framequeue_queued_samples(&inlink->fifo) >= inlink->min_samples;
146
+        if ((flags & AV_BUFFERSINK_FLAG_NO_REQUEST) && !peek_in_framequeue)
140 147
             return AVERROR(EAGAIN);
141 148
         if ((ret = ff_request_frame(inlink)) < 0)
142 149
             return ret;
143
-        while (inlink->frame_wanted_out) {
150
+        frame_count = inlink->frame_count_out;
151
+        while (frame_count == inlink->frame_count_out) {
144 152
             ret = ff_filter_graph_run_once(ctx->graph);
145 153
             if (ret < 0)
146 154
                 return ret;
... ...
@@ -184,6 +184,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
184 184
 
185 185
     if (!frame) {
186 186
         s->eof = 1;
187
+        ff_avfilter_link_set_in_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE);
187 188
         return 0;
188 189
     } else if (s->eof)
189 190
         return AVERROR(EINVAL);
... ...
@@ -235,9 +236,8 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx,
235 235
         return ret;
236 236
     }
237 237
 
238
-    if ((flags & AV_BUFFERSRC_FLAG_PUSH))
239
-        if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
240
-            return ret;
238
+    if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
239
+        return ret;
241 240
 
242 241
     return 0;
243 242
 }
... ...
@@ -26,6 +26,10 @@
26 26
 #include "libavutil/avassert.h"
27 27
 #include "libavutil/avstring.h"
28 28
 #include "libavutil/opt.h"
29
+
30
+#define FF_INTERNAL_FIELDS 1
31
+#include "framequeue.h"
32
+
29 33
 #include "avfilter.h"
30 34
 #include "bufferqueue.h"
31 35
 #include "formats.h"
... ...
@@ -59,7 +63,7 @@ inline static int push_frame(AVFilterContext *ctx)
59 59
     for (i = 0; i < ctx->nb_inputs; i++) {
60 60
         struct FFBufQueue *q = &s->queues[i];
61 61
 
62
-        if (!q->available && !ctx->inputs[i]->status)
62
+        if (!q->available && !ctx->inputs[i]->status_out)
63 63
             return 0;
64 64
         if (q->available) {
65 65
             frame = ff_bufqueue_peek(q, 0);
... ...
@@ -190,7 +194,7 @@ static int request_frame(AVFilterLink *outlink)
190 190
     int i, ret;
191 191
 
192 192
     for (i = 0; i < ctx->nb_inputs; i++) {
193
-        if (!s->queues[i].available && !ctx->inputs[i]->status) {
193
+        if (!s->queues[i].available && !ctx->inputs[i]->status_out) {
194 194
             ret = ff_request_frame(ctx->inputs[i]);
195 195
             if (ret != AVERROR_EOF)
196 196
                 return ret;
... ...
@@ -29,6 +29,7 @@
29 29
 #include "avfiltergraph.h"
30 30
 #include "formats.h"
31 31
 #include "framepool.h"
32
+#include "framequeue.h"
32 33
 #include "thread.h"
33 34
 #include "version.h"
34 35
 #include "video.h"
... ...
@@ -147,6 +148,7 @@ struct AVFilterPad {
147 147
 struct AVFilterGraphInternal {
148 148
     void *thread;
149 149
     avfilter_execute_func *thread_execute;
150
+    FFFrameQueueGlobal frame_queues;
150 151
 };
151 152
 
152 153
 struct AVFilterInternal {
... ...
@@ -336,6 +338,8 @@ int ff_request_frame(AVFilterLink *link);
336 336
 
337 337
 int ff_request_frame_to_filter(AVFilterLink *link);
338 338
 
339
+int ff_filter_frame_to_filter(AVFilterLink *link);
340
+
339 341
 #define AVFILTER_DEFINE_CLASS(fname)            \
340 342
     static const AVClass fname##_class = {      \
341 343
         .class_name = #fname,                   \
... ...
@@ -376,6 +380,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame);
376 376
  */
377 377
 AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
378 378
 
379
+int ff_filter_activate(AVFilterContext *filter);
380
+
379 381
 /**
380 382
  * Remove a filter from a graph;
381 383
  */
... ...
@@ -30,6 +30,9 @@
30 30
 #include "libavutil/mem.h"
31 31
 #include "libavutil/opt.h"
32 32
 
33
+#define FF_INTERNAL_FIELDS 1
34
+#include "framequeue.h"
35
+
33 36
 #include "avfilter.h"
34 37
 #include "audio.h"
35 38
 #include "formats.h"
... ...
@@ -78,7 +81,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
78 78
     for (i = 0; i < ctx->nb_outputs; i++) {
79 79
         AVFrame *buf_out;
80 80
 
81
-        if (ctx->outputs[i]->status)
81
+        if (ctx->outputs[i]->status_in)
82 82
             continue;
83 83
         buf_out = av_frame_clone(frame);
84 84
         if (!buf_out) {
... ...
@@ -25,6 +25,9 @@
25 25
 #include "libavutil/pixdesc.h"
26 26
 #include "libavutil/samplefmt.h"
27 27
 
28
+#define FF_INTERNAL_FIELDS 1
29
+#include "libavfilter/framequeue.h"
30
+
28 31
 #include "libavfilter/avfilter.h"
29 32
 #include "libavfilter/formats.h"
30 33
 
... ...
@@ -22,6 +22,10 @@
22 22
 #include "libavutil/imgutils.h"
23 23
 #include "libavutil/opt.h"
24 24
 #include "libavutil/pixdesc.h"
25
+
26
+#define FF_INTERNAL_FIELDS 1
27
+#include "libavfilter/framequeue.h"
28
+
25 29
 #include "avfilter.h"
26 30
 #include "drawutils.h"
27 31
 #include "internal.h"
... ...
@@ -283,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
283 283
         const int idx = s->map[i];
284 284
         AVFrame *out;
285 285
 
286
-        if (outlink->status)
286
+        if (outlink->status_in)
287 287
             continue;
288 288
 
289 289
         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);