History

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 committed 10 years ago

Commit 02aa0701 parent 62b11db10 files · +493 −143Browse files

Unified · Split

10 files
  1. libavfilter/avfilter.c +381 −76
  2. libavfilter/avfilter.h +52 −19
  3. libavfilter/avfiltergraph.c +17 −36
  4. libavfilter/buffersink.c +16 −5
  5. libavfilter/buffersrc.c +3 −3
  6. libavfilter/f_interleave.c +6 −2
  7. libavfilter/internal.h +6 −0
  8. libavfilter/split.c +4 −1
  9. libavfilter/tests/filtfmts.c +3 −0
  10. libavfilter/vf_extractplanes.c +5 −1
libavfilter/avfilter.c+381−76
@@ -34,6 +34,9 @@ · 33 unmodified lines
3434 #include "libavutil/rational.h"
3535 #include "libavutil/samplefmt.h"
3636
37+#define FF_INTERNAL_FIELDS 1
38+#include "framequeue.h"
39+
3740 #include "audio.h"
3841 #include "avfilter.h"
3942 #include "formats.h"
@@ -135,6 +138,10 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, · 95 unmodified lines
135138 {
136139 AVFilterLink *link;
137140
141+ av_assert0(src->graph);
142+ av_assert0(dst->graph);
143+ av_assert0(src->graph == dst->graph);
144+
138145 if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad ||
139146 src->outputs[srcpad] || dst->inputs[dstpad])
140147 return AVERROR(EINVAL);
@@ -160,6 +167,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, · 19 unmodified lines
160167 link->type = src->output_pads[srcpad].type;
161168 av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
162169 link->format = -1;
170+ ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
163171
164172 return 0;
165173 }
@@ -170,6 +178,7 @@ void avfilter_link_free(AVFilterLink **link) · 4 unmodified lines
170178 return;
171179
172180 av_frame_free(&(*link)->partial_buf);
181+ ff_framequeue_free(&(*link)->fifo);
173182 ff_video_frame_pool_uninit((FFVideoFramePool**)&(*link)->video_frame_pool);
174183
175184 av_freep(link);
@@ -180,16 +189,46 @@ int avfilter_link_get_channels(AVFilterLink *link) · 4 unmodified lines
180189 return link->channels;
181190 }
182191
192+static void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
193+{
194+ filter->ready = FFMAX(filter->ready, priority);
195+}
196+
197+/**
198+ * Clear frame_blocked_in on all outputs.
199+ * This is necessary whenever something changes on input.
200+ */
201+static void filter_unblock(AVFilterContext *filter)
202+{
203+ unsigned i;
204+
205+ for (i = 0; i < filter->nb_outputs; i++)
206+ filter->outputs[i]->frame_blocked_in = 0;
207+}
208+
209+
183210 void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
184211 {
185− ff_avfilter_link_set_out_status(link, status, pts);
212+ if (link->status_in == status)
213+ return;
214+ av_assert0(!link->status_in);
215+ link->status_in = status;
216+ link->status_in_pts = pts;
217+ link->frame_wanted_out = 0;
218+ link->frame_blocked_in = 0;
219+ filter_unblock(link->dst);
220+ ff_filter_set_ready(link->dst, 200);
186221 }
187222
188223 void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
189224 {
190− link->status = status;
191− link->frame_wanted_in = link->frame_wanted_out = 0;
192− ff_update_link_current_pts(link, pts);
225+ av_assert0(!link->frame_wanted_out);
226+ av_assert0(!link->status_out);
227+ link->status_out = status;
228+ if (pts != AV_NOPTS_VALUE)
229+ ff_update_link_current_pts(link, pts);
230+ filter_unblock(link->dst);
231+ ff_filter_set_ready(link->src, 200);
193232 }
194233
195234 void avfilter_link_set_closed(AVFilterLink *link, int closed)
@@ -370,10 +409,23 @@ int ff_request_frame(AVFilterLink *link) · 174 unmodified lines
370409 {
371410 FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
372411
373− if (link->status)
374− return link->status;
375− link->frame_wanted_in = 1;
412+ if (link->status_out)
413+ return link->status_out;
414+ if (link->status_in) {
415+ if (ff_framequeue_queued_frames(&link->fifo)) {
416+ av_assert1(!link->frame_wanted_out);
417+ av_assert1(link->dst->ready >= 300);
418+ return 0;
419+ } else {
420+ /* Acknowledge status change. Filters using ff_request_frame() will
421+ handle the change automatically. Filters can also check the
422+ status directly but none do yet. */
423+ ff_avfilter_link_set_out_status(link, link->status_in, link->status_in_pts);
424+ return link->status_out;
425+ }
426+ }
376427 link->frame_wanted_out = 1;
428+ ff_filter_set_ready(link->src, 100);
377429 return 0;
378430 }
379431
@@ -382,22 +434,17 @@ int ff_request_frame_to_filter(AVFilterLink *link) · 2 unmodified lines
382434 int ret = -1;
383435
384436 FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1);
385− link->frame_wanted_in = 0;
437+ /* Assume the filter is blocked, let the method clear it if not */
438+ link->frame_blocked_in = 1;
386439 if (link->srcpad->request_frame)
387440 ret = link->srcpad->request_frame(link);
388441 else if (link->src->inputs[0])
389442 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− }
398443 if (ret < 0) {
399− if (ret != AVERROR(EAGAIN) && ret != link->status)
444+ if (ret != AVERROR(EAGAIN) && ret != link->status_in)
400445 ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE);
446+ if (ret == AVERROR_EOF)
447+ ret = 0;
401448 }
402449 return ret;
403450 }
@@ -1056,11 +1103,6 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) · 652 unmodified lines
10561103 AVFilterCommand *cmd= link->dst->command_queue;
10571104 int64_t pts;
10581105
1059− if (link->status) {
1060− av_frame_free(&frame);
1061− return link->status;
1062− }
1063−
10641106 if (!(filter_frame = dst->filter_frame))
10651107 filter_frame = default_filter_frame;
10661108
@@ -1142,52 +1184,9 @@ fail: · 75 unmodified lines
11421184 return ret;
11431185 }
11441186
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−
11891187 int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
11901188 {
1189+ int ret;
11911190 FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
11921191
11931192 /* Consistency checks */
@@ -1220,23 +1219,329 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) · 26 unmodified lines
12201219 }
12211220 }
12221221
1223− link->frame_wanted_out = 0;
1222+ link->frame_blocked_in = link->frame_wanted_out = 0;
12241223 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);
1224+ filter_unblock(link->dst);
1225+ ret = ff_framequeue_add(&link->fifo, frame);
1226+ if (ret < 0) {
1227+ av_frame_free(&frame);
1228+ return ret;
12341229 }
1230+ ff_filter_set_ready(link->dst, 300);
1231+ return 0;
1232+
12351233 error:
12361234 av_frame_free(&frame);
12371235 return AVERROR_PATCHWELCOME;
12381236 }
12391237
1238+static int samples_ready(AVFilterLink *link)
1239+{
1240+ return ff_framequeue_queued_frames(&link->fifo) &&
1241+ (ff_framequeue_queued_samples(&link->fifo) >= link->min_samples ||
1242+ link->status_in);
1243+}
1244+
1245+static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
1246+ AVFrame **rframe)
1247+{
1248+ AVFrame *frame0, *frame, *buf;
1249+ unsigned nb_samples, nb_frames, i, p;
1250+ int ret;
1251+
1252+ /* Note: this function relies on no format changes and must only be
1253+ called with enough samples. */
1254+ av_assert1(samples_ready(link));
1255+ frame0 = frame = ff_framequeue_peek(&link->fifo, 0);
1256+ if (frame->nb_samples >= min && frame->nb_samples < max) {
1257+ *rframe = ff_framequeue_take(&link->fifo);
1258+ return 0;
1259+ }
1260+ nb_frames = 0;
1261+ nb_samples = 0;
1262+ while (1) {
1263+ if (nb_samples + frame->nb_samples > max) {
1264+ if (nb_samples < min)
1265+ nb_samples = max;
1266+ break;
1267+ }
1268+ nb_samples += frame->nb_samples;
1269+ nb_frames++;
1270+ if (nb_frames == ff_framequeue_queued_frames(&link->fifo))
1271+ break;
1272+ frame = ff_framequeue_peek(&link->fifo, nb_frames);
1273+ }
1274+
1275+ buf = ff_get_audio_buffer(link, nb_samples);
1276+ if (!buf)
1277+ return AVERROR(ENOMEM);
1278+ ret = av_frame_copy_props(buf, frame0);
1279+ if (ret < 0) {
1280+ av_frame_free(&buf);
1281+ return ret;
1282+ }
1283+ buf->pts = frame0->pts;
1284+
1285+ p = 0;
1286+ for (i = 0; i < nb_frames; i++) {
1287+ frame = ff_framequeue_take(&link->fifo);
1288+ av_samples_copy(buf->extended_data, frame->extended_data, p, 0,
1289+ frame->nb_samples, link->channels, link->format);
1290+ p += frame->nb_samples;
1291+ }
1292+ if (p < nb_samples) {
1293+ unsigned n = nb_samples - p;
1294+ frame = ff_framequeue_peek(&link->fifo, 0);
1295+ av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
1296+ link->channels, link->format);
1297+ frame->nb_samples -= n;
1298+ av_samples_copy(frame->extended_data, frame->extended_data, 0, n,
1299+ frame->nb_samples, link->channels, link->format);
1300+ if (frame->pts != AV_NOPTS_VALUE)
1301+ frame->pts += av_rescale_q(n, av_make_q(1, link->sample_rate), link->time_base);
1302+ ff_framequeue_update_peeked(&link->fifo, 0);
1303+ ff_framequeue_skip_samples(&link->fifo, n);
1304+ }
1305+
1306+ *rframe = buf;
1307+ return 0;
1308+}
1309+
1310+int ff_filter_frame_to_filter(AVFilterLink *link)
1311+{
1312+ AVFrame *frame;
1313+ AVFilterContext *dst = link->dst;
1314+ int ret;
1315+
1316+ av_assert1(ff_framequeue_queued_frames(&link->fifo));
1317+ if (link->min_samples) {
1318+ int min = link->min_samples;
1319+ if (link->status_in)
1320+ min = FFMIN(min, ff_framequeue_queued_samples(&link->fifo));
1321+ ret = take_samples(link, min, link->max_samples, &frame);
1322+ if (ret < 0)
1323+ return ret;
1324+ } else {
1325+ frame = ff_framequeue_take(&link->fifo);
1326+ }
1327+ /* The filter will soon have received a new frame, that may allow it to
1328+ produce one or more: unblock its outputs. */
1329+ filter_unblock(dst);
1330+ ret = ff_filter_frame_framed(link, frame);
1331+ if (ret < 0 && ret != link->status_out) {
1332+ ff_avfilter_link_set_out_status(link, ret, AV_NOPTS_VALUE);
1333+ } else {
1334+ /* Run once again, to see if several frames were available, or if
1335+ the input status has also changed, or any other reason. */
1336+ ff_filter_set_ready(dst, 300);
1337+ }
1338+ return ret;
1339+}
1340+
1341+static int forward_status_change(AVFilterContext *filter, AVFilterLink *in)
1342+{
1343+ unsigned out = 0, progress = 0;
1344+ int ret;
1345+
1346+ av_assert0(!in->status_out);
1347+ if (!filter->nb_outputs) {
1348+ /* not necessary with the current API and sinks */
1349+ return 0;
1350+ }
1351+ while (!in->status_out) {
1352+ if (!filter->outputs[out]->status_in) {
1353+ progress++;
1354+ ret = ff_request_frame_to_filter(filter->outputs[out]);
1355+ if (ret < 0)
1356+ return ret;
1357+ }
1358+ if (++out == filter->nb_outputs) {
1359+ if (!progress) {
1360+ /* Every output already closed: input no longer interesting
1361+ (example: overlay in shortest mode, other input closed). */
1362+ ff_avfilter_link_set_out_status(in, in->status_in, in->status_in_pts);
1363+ return 0;
1364+ }
1365+ progress = 0;
1366+ out = 0;
1367+ }
1368+ }
1369+ ff_filter_set_ready(filter, 200);
1370+ return 0;
1371+}
1372+
1373+#define FFERROR_NOT_READY FFERRTAG('N','R','D','Y')
1374+
1375+static int ff_filter_activate_default(AVFilterContext *filter)
1376+{
1377+ unsigned i;
1378+
1379+ for (i = 0; i < filter->nb_inputs; i++) {
1380+ if (samples_ready(filter->inputs[i])) {
1381+ return ff_filter_frame_to_filter(filter->inputs[i]);
1382+ }
1383+ }
1384+ for (i = 0; i < filter->nb_inputs; i++) {
1385+ if (filter->inputs[i]->status_in && !filter->inputs[i]->status_out) {
1386+ av_assert1(!ff_framequeue_queued_frames(&filter->inputs[i]->fifo));
1387+ return forward_status_change(filter, filter->inputs[i]);
1388+ }
1389+ }
1390+ for (i = 0; i < filter->nb_outputs; i++) {
1391+ if (filter->outputs[i]->frame_wanted_out &&
1392+ !filter->outputs[i]->frame_blocked_in) {
1393+ return ff_request_frame_to_filter(filter->outputs[i]);
1394+ }
1395+ }
1396+ return FFERROR_NOT_READY;
1397+}
1398+
1399+/*
1400+ Filter scheduling and activation
1401+
1402+ When a filter is activated, it must:
1403+ - if possible, output a frame;
1404+ - else, if relevant, forward the input status change;
1405+ - else, check outputs for wanted frames and forward the requests.
1406+
1407+ The following AVFilterLink fields are used for activation:
1408+
1409+ - frame_wanted_out:
1410+
1411+ This field indicates if a frame is needed on this input of the
1412+ destination filter. A positive value indicates that a frame is needed
1413+ to process queued frames or internal data or to satisfy the
1414+ application; a zero value indicates that a frame is not especially
1415+ needed but could be processed anyway; a negative value indicates that a
1416+ frame would just be queued.
1417+
1418+ It is set by filters using ff_request_frame() or ff_request_no_frame(),
1419+ when requested by the application through a specific API or when it is
1420+ set on one of the outputs.
1421+
1422+ It is cleared when a frame is sent from the source using
1423+ ff_filter_frame().
1424+
1425+ It is also cleared when a status change is sent from the source using
1426+ ff_avfilter_link_set_in_status().
1427+
1428+ - frame_blocked_in:
1429+
1430+ This field means that the source filter can not generate a frame as is.
1431+ Its goal is to avoid repeatedly calling the request_frame() method on
1432+ the same link.
1433+
1434+ It is set by the framework on all outputs of a filter before activating it.
1435+
1436+ It is automatically cleared by ff_filter_frame().
1437+
1438+ It is also automatically cleared by ff_avfilter_link_set_in_status().
1439+
1440+ It is also cleared on all outputs (using filter_unblock()) when
1441+ something happens on an input: processing a frame or changing the
1442+ status.
1443+
1444+ - fifo:
1445+
1446+ Contains the frames queued on a filter input. If it contains frames and
1447+ frame_wanted_out is not set, then the filter can be activated. If that
1448+ result in the filter not able to use these frames, the filter must set
1449+ frame_wanted_out to ask for more frames.
1450+
1451+ - status_in and status_in_pts:
1452+
1453+ Status (EOF or error code) of the link and timestamp of the status
1454+ change (in link time base, same as frames) as seen from the input of
1455+ the link. The status change is considered happening after the frames
1456+ queued in fifo.
1457+
1458+ It is set by the source filter using ff_avfilter_link_set_in_status().
1459+
1460+ - status_out:
1461+
1462+ Status of the link as seen from the output of the link. The status
1463+ change is considered having already happened.
1464+
1465+ It is set by the destination filter using
1466+ ff_avfilter_link_set_out_status().
1467+
1468+ Filters are activated according to the ready field, set using the
1469+ ff_filter_set_ready(). Eventually, a priority queue will be used.
1470+ ff_filter_set_ready() is called whenever anything could cause progress to
1471+ be possible. Marking a filter ready when it is not is not a problem,
1472+ except for the small overhead it causes.
1473+
1474+ Conditions that cause a filter to be marked ready are:
1475+
1476+ - frames added on an input link;
1477+
1478+ - changes in the input or output status of an input link;
1479+
1480+ - requests for a frame on an output link;
1481+
1482+ - after any actual processing using the legacy methods (filter_frame(),
1483+ and request_frame() to acknowledge status changes), to run once more
1484+ and check if enough input was present for several frames.
1485+
1486+ Exemples of scenarios to consider:
1487+
1488+ - buffersrc: activate if frame_wanted_out to notify the application;
1489+ activate when the application adds a frame to push it immediately.
1490+
1491+ - testsrc: activate only if frame_wanted_out to produce and push a frame.
1492+
1493+ - concat (not at stitch points): can process a frame on any output.
1494+ Activate if frame_wanted_out on output to forward on the corresponding
1495+ input. Activate when a frame is present on input to process it
1496+ immediately.
1497+
1498+ - framesync: needs at least one frame on each input; extra frames on the
1499+ wrong input will accumulate. When a frame is first added on one input,
1500+ set frame_wanted_out<0 on it to avoid getting more (would trigger
1501+ testsrc) and frame_wanted_out>0 on the other to allow processing it.
1502+
1503+ Activation of old filters:
1504+
1505+ In order to activate a filter implementing the legacy filter_frame() and
1506+ request_frame() methods, perform the first possible of the following
1507+ actions:
1508+
1509+ - If an input has frames in fifo and frame_wanted_out == 0, dequeue a
1510+ frame and call filter_frame().
1511+
1512+ Ratinale: filter frames as soon as possible instead of leaving them
1513+ queued; frame_wanted_out < 0 is not possible since the old API does not
1514+ set it nor provides any similar feedback; frame_wanted_out > 0 happens
1515+ when min_samples > 0 and there are not enough samples queued.
1516+
1517+ - If an input has status_in set but not status_out, try to call
1518+ request_frame() on one of the outputs in the hope that it will trigger
1519+ request_frame() on the input with status_in and acknowledge it. This is
1520+ awkward and fragile, filters with several inputs or outputs should be
1521+ updated to direct activation as soon as possible.
1522+
1523+ - If an output has frame_wanted_out > 0 and not frame_blocked_in, call
1524+ request_frame().
1525+
1526+ Rationale: checking frame_blocked_in is necessary to avoid requesting
1527+ repeatedly on a blocked input if another is not blocked (example:
1528+ [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2).
1529+
1530+ TODO: respect needs_fifo and remove auto-inserted fifos.
1531+
1532+ */
1533+
1534+int ff_filter_activate(AVFilterContext *filter)
1535+{
1536+ int ret;
1537+
1538+ filter->ready = 0;
1539+ ret = ff_filter_activate_default(filter);
1540+ if (ret == FFERROR_NOT_READY)
1541+ ret = 0;
1542+ return ret;
1543+}
1544+
12401545 const AVClass *avfilter_get_class(void)
12411546 {
12421547 return &avfilter_class;
libavfilter/avfilter.h+52−19
@@ -368,6 +368,13 @@ struct AVFilterContext { · 367 unmodified lines
368368 * Overrides global number of threads set per filter graph.
369369 */
370370 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;
371378 };
372379
373380 /**
@@ -508,18 +515,6 @@ struct AVFilterLink { · 134 unmodified lines
508515 */
509516 int max_samples;
510517
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−
523518 /**
524519 * Number of channels.
525520 */
@@ -540,13 +535,6 @@ struct AVFilterLink { · 14 unmodified lines
540535 */
541536 void *video_frame_pool;
542537
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−
550538 /**
551539 * True if a frame is currently wanted on the output of this filter.
552540 * Set when ff_request_frame() is called by the output,
@@ -559,6 +547,51 @@ struct AVFilterLink { · 6 unmodified lines
559547 * AVHWFramesContext describing the frames.
560548 */
561549 AVBufferRef *hw_frames_ctx;
550+
551+#ifndef FF_INTERNAL_FIELDS
552+
553+ /**
554+ * Internal structure members.
555+ * The fields below this limit are internal for libavfilter's use
556+ * and must in no way be accessed by applications.
557+ */
558+ char reserved[0xF000];
559+
560+#else /* FF_INTERNAL_FIELDS */
561+
562+ /**
563+ * Queue of frames waiting to be filtered.
564+ */
565+ FFFrameQueue fifo;
566+
567+ /**
568+ * If set, the source filter can not generate a frame as is.
569+ * The goal is to avoid repeatedly calling the request_frame() method on
570+ * the same link.
571+ */
572+ int frame_blocked_in;
573+
574+ /**
575+ * Link input status.
576+ * If not zero, all attempts of filter_frame will fail with the
577+ * corresponding code.
578+ */
579+ int status_in;
580+
581+ /**
582+ * Timestamp of the input status change.
583+ */
584+ int64_t status_in_pts;
585+
586+ /**
587+ * Link output status.
588+ * If not zero, all attempts of request_frame will fail with the
589+ * corresponding code.
590+ */
591+ int status_out;
592+
593+#endif /* FF_INTERNAL_FIELDS */
594+
562595 };
563596
564597 /**
libavfilter/avfiltergraph.c+17−36
@@ -32,6 +32,9 @@ · 31 unmodified lines
3232 #include "libavutil/opt.h"
3333 #include "libavutil/pixdesc.h"
3434
35+#define FF_INTERNAL_FIELDS 1
36+#include "framequeue.h"
37+
3538 #include "avfilter.h"
3639 #include "formats.h"
3740 #include "internal.h"
@@ -87,6 +90,7 @@ AVFilterGraph *avfilter_graph_alloc(void) · 49 unmodified lines
8790
8891 ret->av_class = &filtergraph_class;
8992 av_opt_set_defaults(ret);
93+ ff_framequeue_global_init(&ret->internal->frame_queues);
9094
9195 return ret;
9296 }
@@ -1377,10 +1381,10 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link) · 1284 unmodified lines
13771381 heap_bubble_down(graph, link, link->age_index);
13781382 }
13791383
1380−
13811384 int avfilter_graph_request_oldest(AVFilterGraph *graph)
13821385 {
13831386 AVFilterLink *oldest = graph->sink_links[0];
1387+ int64_t frame_count;
13841388 int r;
13851389
13861390 while (graph->sink_links_count) {
@@ -1400,7 +1404,8 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) · 13 unmodified lines
14001404 if (!graph->sink_links_count)
14011405 return AVERROR_EOF;
14021406 av_assert1(oldest->age_index >= 0);
1403− while (oldest->frame_wanted_out) {
1407+ frame_count = oldest->frame_count_out;
1408+ while (frame_count == oldest->frame_count_out) {
14041409 r = ff_filter_graph_run_once(graph);
14051410 if (r < 0)
14061411 return r;
@@ -1408,41 +1413,17 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) · 1 unmodified line
14081413 return 0;
14091414 }
14101415
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−
14321416 int ff_filter_graph_run_once(AVFilterGraph *graph)
14331417 {
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");
1418+ AVFilterContext *filter;
1419+ unsigned i;
1420+
1421+ av_assert0(graph->nb_filters);
1422+ filter = graph->filters[0];
1423+ for (i = 1; i < graph->nb_filters; i++)
1424+ if (graph->filters[i]->ready > filter->ready)
1425+ filter = graph->filters[i];
1426+ if (!filter->ready)
14401427 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;
1428+ return ff_filter_activate(filter);
14481429 }
libavfilter/buffersink.c+16−5
@@ -31,6 +31,9 @@ · 30 unmodified lines
3131 #include "libavutil/mathematics.h"
3232 #include "libavutil/opt.h"
3333
34+#define FF_INTERNAL_FIELDS 1
35+#include "framequeue.h"
36+
3437 #include "audio.h"
3538 #include "avfilter.h"
3639 #include "buffersink.h"
@@ -129,18 +132,26 @@ int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFr · 92 unmodified lines
129132 {
130133 BufferSinkContext *buf = ctx->priv;
131134 AVFilterLink *inlink = ctx->inputs[0];
132− int ret;
135+ int peek_in_framequeue = 0, ret;
136+ int64_t frame_count;
133137 AVFrame *cur_frame;
134138
135139 /* no picref available, fetch it from the filterchain */
136140 while (!av_fifo_size(buf->fifo)) {
137− if (inlink->status)
138− return inlink->status;
139− if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
141+ /* if peek_in_framequeue is true later, then ff_request_frame() and
142+ the ff_filter_graph_run_once() loop will take a frame from it and
143+ move it to the internal fifo, ending the global loop */
144+ av_assert0(!peek_in_framequeue);
145+ if (inlink->status_out)
146+ return inlink->status_out;
147+ peek_in_framequeue = ff_framequeue_queued_frames(&inlink->fifo) &&
148+ ff_framequeue_queued_samples(&inlink->fifo) >= inlink->min_samples;
149+ if ((flags & AV_BUFFERSINK_FLAG_NO_REQUEST) && !peek_in_framequeue)
140150 return AVERROR(EAGAIN);
141151 if ((ret = ff_request_frame(inlink)) < 0)
142152 return ret;
143− while (inlink->frame_wanted_out) {
153+ frame_count = inlink->frame_count_out;
154+ while (frame_count == inlink->frame_count_out) {
144155 ret = ff_filter_graph_run_once(ctx->graph);
145156 if (ret < 0)
146157 return ret;
libavfilter/buffersrc.c+3−3
@@ -184,6 +184,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, · 183 unmodified lines
184184
185185 if (!frame) {
186186 s->eof = 1;
187+ ff_avfilter_link_set_in_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE);
187188 return 0;
188189 } else if (s->eof)
189190 return AVERROR(EINVAL);
@@ -235,9 +236,8 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, · 45 unmodified lines
235236 return ret;
236237 }
237238
238− if ((flags & AV_BUFFERSRC_FLAG_PUSH))
239− if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
240− return ret;
239+ if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
240+ return ret;
241241
242242 return 0;
243243 }
libavfilter/f_interleave.c+6−2
@@ -26,6 +26,10 @@ · 25 unmodified lines
2626 #include "libavutil/avassert.h"
2727 #include "libavutil/avstring.h"
2828 #include "libavutil/opt.h"
29+
30+#define FF_INTERNAL_FIELDS 1
31+#include "framequeue.h"
32+
2933 #include "avfilter.h"
3034 #include "bufferqueue.h"
3135 #include "formats.h"
@@ -59,7 +63,7 @@ inline static int push_frame(AVFilterContext *ctx) · 27 unmodified lines
5963 for (i = 0; i < ctx->nb_inputs; i++) {
6064 struct FFBufQueue *q = &s->queues[i];
6165
62− if (!q->available && !ctx->inputs[i]->status)
66+ if (!q->available && !ctx->inputs[i]->status_out)
6367 return 0;
6468 if (q->available) {
6569 frame = ff_bufqueue_peek(q, 0);
@@ -190,7 +194,7 @@ static int request_frame(AVFilterLink *outlink) · 124 unmodified lines
190194 int i, ret;
191195
192196 for (i = 0; i < ctx->nb_inputs; i++) {
193− if (!s->queues[i].available && !ctx->inputs[i]->status) {
197+ if (!s->queues[i].available && !ctx->inputs[i]->status_out) {
194198 ret = ff_request_frame(ctx->inputs[i]);
195199 if (ret != AVERROR_EOF)
196200 return ret;
libavfilter/internal.h+6−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
2929 #include "avfiltergraph.h"
3030 #include "formats.h"
3131 #include "framepool.h"
32+#include "framequeue.h"
3233 #include "thread.h"
3334 #include "version.h"
3435 #include "video.h"
@@ -147,6 +148,7 @@ struct AVFilterPad { · 112 unmodified lines
147148 struct AVFilterGraphInternal {
148149 void *thread;
149150 avfilter_execute_func *thread_execute;
151+ FFFrameQueueGlobal frame_queues;
150152 };
151153
152154 struct AVFilterInternal {
@@ -336,6 +338,8 @@ int ff_request_frame(AVFilterLink *link); · 183 unmodified lines
336338
337339 int ff_request_frame_to_filter(AVFilterLink *link);
338340
341+int ff_filter_frame_to_filter(AVFilterLink *link);
342+
339343 #define AVFILTER_DEFINE_CLASS(fname) \
340344 static const AVClass fname##_class = { \
341345 .class_name = #fname, \
@@ -376,6 +380,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame); · 34 unmodified lines
376380 */
377381 AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
378382
383+int ff_filter_activate(AVFilterContext *filter);
384+
379385 /**
380386 * Remove a filter from a graph;
381387 */
libavfilter/split.c+4−1
@@ -30,6 +30,9 @@ · 29 unmodified lines
3030 #include "libavutil/mem.h"
3131 #include "libavutil/opt.h"
3232
33+#define FF_INTERNAL_FIELDS 1
34+#include "framequeue.h"
35+
3336 #include "avfilter.h"
3437 #include "audio.h"
3538 #include "formats.h"
@@ -78,7 +81,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 42 unmodified lines
7881 for (i = 0; i < ctx->nb_outputs; i++) {
7982 AVFrame *buf_out;
8083
81− if (ctx->outputs[i]->status)
84+ if (ctx->outputs[i]->status_in)
8285 continue;
8386 buf_out = av_frame_clone(frame);
8487 if (!buf_out) {
libavfilter/tests/filtfmts.c+3−0
@@ -25,6 +25,9 @@ · 24 unmodified lines
2525 #include "libavutil/pixdesc.h"
2626 #include "libavutil/samplefmt.h"
2727
28+#define FF_INTERNAL_FIELDS 1
29+#include "libavfilter/framequeue.h"
30+
2831 #include "libavfilter/avfilter.h"
2932 #include "libavfilter/formats.h"
3033
libavfilter/vf_extractplanes.c+5−1
@@ -22,6 +22,10 @@ · 21 unmodified lines
2222 #include "libavutil/imgutils.h"
2323 #include "libavutil/opt.h"
2424 #include "libavutil/pixdesc.h"
25+
26+#define FF_INTERNAL_FIELDS 1
27+#include "libavfilter/framequeue.h"
28+
2529 #include "avfilter.h"
2630 #include "drawutils.h"
2731 #include "internal.h"
@@ -283,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 255 unmodified lines
283287 const int idx = s->map[i];
284288 AVFrame *out;
285289
286− if (outlink->status)
290+ if (outlink->status_in)
287291 continue;
288292
289293 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);

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