| @@ -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 | |
| | 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 | |
| 183 | void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) | 210 | void 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 | |
| 188 | void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts) | 223 | void 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 | |
| 195 | void avfilter_link_set_closed(AVFilterLink *link, int closed) | 234 | void 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 | |
| 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 | int ff_filter_frame(AVFilterLink *link, AVFrame *frame) | 1187 | int 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 | |
| 1235 | error: | 1233 | error: |
| 1236 | av_frame_free(&frame); | 1234 | av_frame_free(&frame); |
| 1237 | return AVERROR_PATCHWELCOME; | 1235 | return AVERROR_PATCHWELCOME; |
| 1238 | } | 1236 | } |
| 1239 | | 1237 | |
| | 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 | |
| 1240 | const AVClass *avfilter_get_class(void) | 1545 | const AVClass *avfilter_get_class(void) |
| 1241 | { | 1546 | { |
| 1242 | return &avfilter_class; | 1547 | return &avfilter_class; |