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
34#include "libavutil/rational.h"34#include "libavutil/rational.h"
35#include "libavutil/samplefmt.h"35#include "libavutil/samplefmt.h"
36 36
37#define FF_INTERNAL_FIELDS 1
38#include "framequeue.h"
39
37#include "audio.h"40#include "audio.h"
38#include "avfilter.h"41#include "avfilter.h"
39#include "formats.h"42#include "formats.h"
@@ -135,6 +138,10 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, · 95 unmodified lines
135{138{
136 AVFilterLink *link;139 AVFilterLink *link;
137 140
141 av_assert0(src->graph);
142 av_assert0(dst->graph);
143 av_assert0(src->graph == dst->graph);
144
138 if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad ||145 if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad ||
139 src->outputs[srcpad] || dst->inputs[dstpad])146 src->outputs[srcpad] || dst->inputs[dstpad])
140 return AVERROR(EINVAL);147 return AVERROR(EINVAL);
@@ -160,6 +167,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, · 19 unmodified lines
160 link->type = src->output_pads[srcpad].type;167 link->type = src->output_pads[srcpad].type;
161 av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);168 av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
162 link->format = -1;169 link->format = -1;
170 ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
163 171
164 return 0;172 return 0;
165}173}
@@ -170,6 +178,7 @@ void avfilter_link_free(AVFilterLink **link) · 4 unmodified lines
170 return;178 return;
171 179
172 av_frame_free(&(*link)->partial_buf);180 av_frame_free(&(*link)->partial_buf);
181 ff_framequeue_free(&(*link)->fifo);
173 ff_video_frame_pool_uninit((FFVideoFramePool**)&(*link)->video_frame_pool);182 ff_video_frame_pool_uninit((FFVideoFramePool**)&(*link)->video_frame_pool);
174 183
175 av_freep(link);184 av_freep(link);
@@ -180,16 +189,46 @@ int avfilter_link_get_channels(AVFilterLink *link) · 4 unmodified lines
180 return link->channels;189 return link->channels;
181}190}
182 191
192static 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 */
201static 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
183void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)210void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
184{211{
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);
186}221}
187 222
188void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)223void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
189{224{
190 link->status = status;225 av_assert0(!link->frame_wanted_out);
191 link->frame_wanted_in = link->frame_wanted_out = 0;226 av_assert0(!link->status_out);
192 ff_update_link_current_pts(link, pts);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);
193}232}
194 233
195void avfilter_link_set_closed(AVFilterLink *link, int closed)234void avfilter_link_set_closed(AVFilterLink *link, int closed)
@@ -370,10 +409,23 @@ int ff_request_frame(AVFilterLink *link) · 174 unmodified lines
370{409{
371 FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);410 FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
372 411
373 if (link->status)412 if (link->status_out)
374 return link->status;413 return link->status_out;
375 link->frame_wanted_in = 1;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 }
376 link->frame_wanted_out = 1;427 link->frame_wanted_out = 1;
428 ff_filter_set_ready(link->src, 100);
377 return 0;429 return 0;
378}430}
379 431
@@ -382,22 +434,17 @@ int ff_request_frame_to_filter(AVFilterLink *link) · 2 unmodified lines
382 int ret = -1;434 int ret = -1;
383 435
384 FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1);436 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;
386 if (link->srcpad->request_frame)439 if (link->srcpad->request_frame)
387 ret = link->srcpad->request_frame(link);440 ret = link->srcpad->request_frame(link);
388 else if (link->src->inputs[0])441 else if (link->src->inputs[0])
389 ret = ff_request_frame(link->src->inputs[0]);442 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 if (ret < 0) {443 if (ret < 0) {
399 if (ret != AVERROR(EAGAIN) && ret != link->status)444 if (ret != AVERROR(EAGAIN) && ret != link->status_in)
400 ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE);445 ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE);
446 if (ret == AVERROR_EOF)
447 ret = 0;
401 }448 }
402 return ret;449 return ret;
403}450}
@@ -1056,11 +1103,6 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) · 652 unmodified lines
1056 AVFilterCommand *cmd= link->dst->command_queue;1103 AVFilterCommand *cmd= link->dst->command_queue;
1057 int64_t pts;1104 int64_t pts;
1058 1105
1059 if (link->status) {
1060 av_frame_free(&frame);
1061 return link->status;
1062 }
1063
1064 if (!(filter_frame = dst->filter_frame))1106 if (!(filter_frame = dst->filter_frame))
1065 filter_frame = default_filter_frame;1107 filter_frame = default_filter_frame;
1066 1108
@@ -1142,52 +1184,9 @@ fail: · 75 unmodified lines
1142 return ret;1184 return ret;
1143}1185}
1144 1186
1145static 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
1189int ff_filter_frame(AVFilterLink *link, AVFrame *frame)1187int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
1190{1188{
1189 int ret;
1191 FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);1190 FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
1192 1191
1193 /* Consistency checks */1192 /* Consistency checks */
@@ -1220,23 +1219,329 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) · 26 unmodified lines
1220 }1219 }
1221 }1220 }
1222 1221
1223 link->frame_wanted_out = 0;1222 link->frame_blocked_in = link->frame_wanted_out = 0;
1224 link->frame_count_in++;1223 link->frame_count_in++;
1225 /* Go directly to actual filtering if possible */1224 filter_unblock(link->dst);
1226 if (link->type == AVMEDIA_TYPE_AUDIO &&1225 ret = ff_framequeue_add(&link->fifo, frame);
1227 link->min_samples &&1226 if (ret < 0) {
1228 (link->partial_buf ||1227 av_frame_free(&frame);
1229 frame->nb_samples < link->min_samples ||1228 return ret;
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);
1234 }1229 }
1230 ff_filter_set_ready(link->dst, 300);
1231 return 0;
1232
1235error:1233error:
1236 av_frame_free(&frame);1234 av_frame_free(&frame);
1237 return AVERROR_PATCHWELCOME;1235 return AVERROR_PATCHWELCOME;
1238}1236}
1239 1237
1238static 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
1245static 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
1310int 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
1341static 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
1375static 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
1534int 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
1240const AVClass *avfilter_get_class(void)1545const AVClass *avfilter_get_class(void)
1241{1546{
1242 return &avfilter_class;1547 return &avfilter_class;
libavfilter/avfilter.h+52−19
@@ -368,6 +368,13 @@ struct AVFilterContext { · 367 unmodified lines
368 * Overrides global number of threads set per filter graph.368 * Overrides global number of threads set per filter graph.
369 */369 */
370 int nb_threads;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/**
@@ -508,18 +515,6 @@ struct AVFilterLink { · 134 unmodified lines
508 */515 */
509 int max_samples;516 int max_samples;
510 517
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 /**518 /**
524 * Number of channels.519 * Number of channels.
525 */520 */
@@ -540,13 +535,6 @@ struct AVFilterLink { · 14 unmodified lines
540 */535 */
541 void *video_frame_pool;536 void *video_frame_pool;
542 537
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 /**538 /**
551 * True if a frame is currently wanted on the output of this filter.539 * True if a frame is currently wanted on the output of this filter.
552 * Set when ff_request_frame() is called by the output,540 * Set when ff_request_frame() is called by the output,
@@ -559,6 +547,51 @@ struct AVFilterLink { · 6 unmodified lines
559 * AVHWFramesContext describing the frames.547 * AVHWFramesContext describing the frames.
560 */548 */
561 AVBufferRef *hw_frames_ctx;549 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
562};595};
563 596
564/**597/**
libavfilter/avfiltergraph.c+17−36
@@ -32,6 +32,9 @@ · 31 unmodified lines
32#include "libavutil/opt.h"32#include "libavutil/opt.h"
33#include "libavutil/pixdesc.h"33#include "libavutil/pixdesc.h"
34 34
35#define FF_INTERNAL_FIELDS 1
36#include "framequeue.h"
37
35#include "avfilter.h"38#include "avfilter.h"
36#include "formats.h"39#include "formats.h"
37#include "internal.h"40#include "internal.h"
@@ -87,6 +90,7 @@ AVFilterGraph *avfilter_graph_alloc(void) · 49 unmodified lines
87 90
88 ret->av_class = &filtergraph_class;91 ret->av_class = &filtergraph_class;
89 av_opt_set_defaults(ret);92 av_opt_set_defaults(ret);
93 ff_framequeue_global_init(&ret->internal->frame_queues);
90 94
91 return ret;95 return ret;
92}96}
@@ -1377,10 +1381,10 @@ void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link) · 1284 unmodified lines
1377 heap_bubble_down(graph, link, link->age_index);1381 heap_bubble_down(graph, link, link->age_index);
1378}1382}
1379 1383
1380
1381int avfilter_graph_request_oldest(AVFilterGraph *graph)1384int avfilter_graph_request_oldest(AVFilterGraph *graph)
1382{1385{
1383 AVFilterLink *oldest = graph->sink_links[0];1386 AVFilterLink *oldest = graph->sink_links[0];
1387 int64_t frame_count;
1384 int r;1388 int r;
1385 1389
1386 while (graph->sink_links_count) {1390 while (graph->sink_links_count) {
@@ -1400,7 +1404,8 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) · 13 unmodified lines
1400 if (!graph->sink_links_count)1404 if (!graph->sink_links_count)
1401 return AVERROR_EOF;1405 return AVERROR_EOF;
1402 av_assert1(oldest->age_index >= 0);1406 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) {
1404 r = ff_filter_graph_run_once(graph);1409 r = ff_filter_graph_run_once(graph);
1405 if (r < 0)1410 if (r < 0)
1406 return r;1411 return r;
@@ -1408,41 +1413,17 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) · 1 unmodified line
1408 return 0;1413 return 0;
1409}1414}
1410 1415
1411static 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
1432int ff_filter_graph_run_once(AVFilterGraph *graph)1416int ff_filter_graph_run_once(AVFilterGraph *graph)
1433{1417{
1434 AVFilterLink *link;1418 AVFilterContext *filter;
1435 int ret;1419 unsigned i;
1436 1420
1437 link = graph_run_once_find_filter(graph);1421 av_assert0(graph->nb_filters);
1438 if (!link) {1422 filter = graph->filters[0];
1439 av_log(NULL, AV_LOG_WARNING, "Useless run of a filter graph\n");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)
1440 return AVERROR(EAGAIN);1427 return AVERROR(EAGAIN);
1441 }1428 return ff_filter_activate(filter);
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;
1448}1429}
libavfilter/buffersink.c+16−5
@@ -31,6 +31,9 @@ · 30 unmodified lines
31#include "libavutil/mathematics.h"31#include "libavutil/mathematics.h"
32#include "libavutil/opt.h"32#include "libavutil/opt.h"
33 33
34#define FF_INTERNAL_FIELDS 1
35#include "framequeue.h"
36
34#include "audio.h"37#include "audio.h"
35#include "avfilter.h"38#include "avfilter.h"
36#include "buffersink.h"39#include "buffersink.h"
@@ -129,18 +132,26 @@ int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFr · 92 unmodified lines
129{132{
130 BufferSinkContext *buf = ctx->priv;133 BufferSinkContext *buf = ctx->priv;
131 AVFilterLink *inlink = ctx->inputs[0];134 AVFilterLink *inlink = ctx->inputs[0];
132 int ret;135 int peek_in_framequeue = 0, ret;
136 int64_t frame_count;
133 AVFrame *cur_frame;137 AVFrame *cur_frame;
134 138
135 /* no picref available, fetch it from the filterchain */139 /* no picref available, fetch it from the filterchain */
136 while (!av_fifo_size(buf->fifo)) {140 while (!av_fifo_size(buf->fifo)) {
137 if (inlink->status)141 /* if peek_in_framequeue is true later, then ff_request_frame() and
138 return inlink->status;142 the ff_filter_graph_run_once() loop will take a frame from it and
139 if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)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)
140 return AVERROR(EAGAIN);150 return AVERROR(EAGAIN);
141 if ((ret = ff_request_frame(inlink)) < 0)151 if ((ret = ff_request_frame(inlink)) < 0)
142 return ret;152 return ret;
143 while (inlink->frame_wanted_out) {153 frame_count = inlink->frame_count_out;
154 while (frame_count == inlink->frame_count_out) {
144 ret = ff_filter_graph_run_once(ctx->graph);155 ret = ff_filter_graph_run_once(ctx->graph);
145 if (ret < 0)156 if (ret < 0)
146 return ret;157 return ret;
libavfilter/buffersrc.c+3−3
@@ -184,6 +184,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, · 183 unmodified lines
184 184
185 if (!frame) {185 if (!frame) {
186 s->eof = 1;186 s->eof = 1;
187 ff_avfilter_link_set_in_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE);
187 return 0;188 return 0;
188 } else if (s->eof)189 } else if (s->eof)
189 return AVERROR(EINVAL);190 return AVERROR(EINVAL);
@@ -235,9 +236,8 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, · 45 unmodified lines
235 return ret;236 return ret;
236 }237 }
237 238
238 if ((flags & AV_BUFFERSRC_FLAG_PUSH))239 if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)
239 if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0)240 return ret;
240 return ret;
241 241
242 return 0;242 return 0;
243}243}
libavfilter/f_interleave.c+6−2
@@ -26,6 +26,10 @@ · 25 unmodified lines
26#include "libavutil/avassert.h"26#include "libavutil/avassert.h"
27#include "libavutil/avstring.h"27#include "libavutil/avstring.h"
28#include "libavutil/opt.h"28#include "libavutil/opt.h"
29
30#define FF_INTERNAL_FIELDS 1
31#include "framequeue.h"
32
29#include "avfilter.h"33#include "avfilter.h"
30#include "bufferqueue.h"34#include "bufferqueue.h"
31#include "formats.h"35#include "formats.h"
@@ -59,7 +63,7 @@ inline static int push_frame(AVFilterContext *ctx) · 27 unmodified lines
59 for (i = 0; i < ctx->nb_inputs; i++) {63 for (i = 0; i < ctx->nb_inputs; i++) {
60 struct FFBufQueue *q = &s->queues[i];64 struct FFBufQueue *q = &s->queues[i];
61 65
62 if (!q->available && !ctx->inputs[i]->status)66 if (!q->available && !ctx->inputs[i]->status_out)
63 return 0;67 return 0;
64 if (q->available) {68 if (q->available) {
65 frame = ff_bufqueue_peek(q, 0);69 frame = ff_bufqueue_peek(q, 0);
@@ -190,7 +194,7 @@ static int request_frame(AVFilterLink *outlink) · 124 unmodified lines
190 int i, ret;194 int i, ret;
191 195
192 for (i = 0; i < ctx->nb_inputs; i++) {196 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) {
194 ret = ff_request_frame(ctx->inputs[i]);198 ret = ff_request_frame(ctx->inputs[i]);
195 if (ret != AVERROR_EOF)199 if (ret != AVERROR_EOF)
196 return ret;200 return ret;
libavfilter/internal.h+6−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
29#include "avfiltergraph.h"29#include "avfiltergraph.h"
30#include "formats.h"30#include "formats.h"
31#include "framepool.h"31#include "framepool.h"
32#include "framequeue.h"
32#include "thread.h"33#include "thread.h"
33#include "version.h"34#include "version.h"
34#include "video.h"35#include "video.h"
@@ -147,6 +148,7 @@ struct AVFilterPad { · 112 unmodified lines
147struct AVFilterGraphInternal {148struct AVFilterGraphInternal {
148 void *thread;149 void *thread;
149 avfilter_execute_func *thread_execute;150 avfilter_execute_func *thread_execute;
151 FFFrameQueueGlobal frame_queues;
150};152};
151 153
152struct AVFilterInternal {154struct AVFilterInternal {
@@ -336,6 +338,8 @@ int ff_request_frame(AVFilterLink *link); · 183 unmodified lines
336 338
337int ff_request_frame_to_filter(AVFilterLink *link);339int ff_request_frame_to_filter(AVFilterLink *link);
338 340
341int ff_filter_frame_to_filter(AVFilterLink *link);
342
339#define AVFILTER_DEFINE_CLASS(fname) \343#define AVFILTER_DEFINE_CLASS(fname) \
340 static const AVClass fname##_class = { \344 static const AVClass fname##_class = { \
341 .class_name = #fname, \345 .class_name = #fname, \
@@ -376,6 +380,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame); · 34 unmodified lines
376 */380 */
377AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);381AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name);
378 382
383int ff_filter_activate(AVFilterContext *filter);
384
379/**385/**
380 * Remove a filter from a graph;386 * Remove a filter from a graph;
381 */387 */
libavfilter/split.c+4−1
@@ -30,6 +30,9 @@ · 29 unmodified lines
30#include "libavutil/mem.h"30#include "libavutil/mem.h"
31#include "libavutil/opt.h"31#include "libavutil/opt.h"
32 32
33#define FF_INTERNAL_FIELDS 1
34#include "framequeue.h"
35
33#include "avfilter.h"36#include "avfilter.h"
34#include "audio.h"37#include "audio.h"
35#include "formats.h"38#include "formats.h"
@@ -78,7 +81,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 42 unmodified lines
78 for (i = 0; i < ctx->nb_outputs; i++) {81 for (i = 0; i < ctx->nb_outputs; i++) {
79 AVFrame *buf_out;82 AVFrame *buf_out;
80 83
81 if (ctx->outputs[i]->status)84 if (ctx->outputs[i]->status_in)
82 continue;85 continue;
83 buf_out = av_frame_clone(frame);86 buf_out = av_frame_clone(frame);
84 if (!buf_out) {87 if (!buf_out) {
libavfilter/tests/filtfmts.c+3−0
@@ -25,6 +25,9 @@ · 24 unmodified lines
25#include "libavutil/pixdesc.h"25#include "libavutil/pixdesc.h"
26#include "libavutil/samplefmt.h"26#include "libavutil/samplefmt.h"
27 27
28#define FF_INTERNAL_FIELDS 1
29#include "libavfilter/framequeue.h"
30
28#include "libavfilter/avfilter.h"31#include "libavfilter/avfilter.h"
29#include "libavfilter/formats.h"32#include "libavfilter/formats.h"
30 33
libavfilter/vf_extractplanes.c+5−1
@@ -22,6 +22,10 @@ · 21 unmodified lines
22#include "libavutil/imgutils.h"22#include "libavutil/imgutils.h"
23#include "libavutil/opt.h"23#include "libavutil/opt.h"
24#include "libavutil/pixdesc.h"24#include "libavutil/pixdesc.h"
25
26#define FF_INTERNAL_FIELDS 1
27#include "libavfilter/framequeue.h"
28
25#include "avfilter.h"29#include "avfilter.h"
26#include "drawutils.h"30#include "drawutils.h"
27#include "internal.h"31#include "internal.h"
@@ -283,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 255 unmodified lines
283 const int idx = s->map[i];287 const int idx = s->map[i];
284 AVFrame *out;288 AVFrame *out;
285 289
286 if (outlink->status)290 if (outlink->status_in)
287 continue;291 continue;
288 292
289 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);293 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