Some filters need several input frames before producing output.
For these filter, it becomes simpler to return 0 in
request_frame() and let the framework call it again until
output has been produced.
... | ... |
@@ -323,6 +323,10 @@ int ff_request_frame(AVFilterLink *link) |
323 | 323 |
|
324 | 324 |
if (link->closed) |
325 | 325 |
return AVERROR_EOF; |
326 |
+ av_assert0(!link->frame_requested); |
|
327 |
+ link->frame_requested = 1; |
|
328 |
+ while (link->frame_requested) { |
|
329 |
+ /* TODO reindent */ |
|
326 | 330 |
if (link->srcpad->request_frame) |
327 | 331 |
ret = link->srcpad->request_frame(link); |
328 | 332 |
else if (link->src->inputs[0]) |
... | ... |
@@ -332,8 +336,15 @@ int ff_request_frame(AVFilterLink *link) |
332 | 332 |
link->partial_buf = NULL; |
333 | 333 |
ret = ff_filter_frame_framed(link, pbuf); |
334 | 334 |
} |
335 |
- if (ret == AVERROR_EOF) |
|
336 |
- link->closed = 1; |
|
335 |
+ if (ret < 0) { |
|
336 |
+ link->frame_requested = 0; |
|
337 |
+ if (ret == AVERROR_EOF) |
|
338 |
+ link->closed = 1; |
|
339 |
+ } else { |
|
340 |
+ av_assert0(!link->frame_requested || |
|
341 |
+ link->flags & FF_LINK_FLAG_REQUEST_LOOP); |
|
342 |
+ } |
|
343 |
+ } |
|
337 | 344 |
return ret; |
338 | 345 |
} |
339 | 346 |
|
... | ... |
@@ -702,6 +713,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) |
702 | 702 |
|
703 | 703 |
pts = out->pts; |
704 | 704 |
ret = filter_frame(link, out); |
705 |
+ link->frame_requested = 0; |
|
705 | 706 |
ff_update_link_current_pts(link, pts); |
706 | 707 |
return ret; |
707 | 708 |
} |
... | ... |
@@ -713,6 +725,7 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) |
713 | 713 |
int nb_channels = av_frame_get_channels(frame); |
714 | 714 |
int ret = 0; |
715 | 715 |
|
716 |
+ link->flags |= FF_LINK_FLAG_REQUEST_LOOP; |
|
716 | 717 |
/* Handle framing (min_samples, max_samples) */ |
717 | 718 |
while (insamples) { |
718 | 719 |
if (!pbuf) { |
... | ... |
@@ -682,6 +682,17 @@ struct AVFilterLink { |
682 | 682 |
* Number of channels. |
683 | 683 |
*/ |
684 | 684 |
int channels; |
685 |
+ |
|
686 |
+ /** |
|
687 |
+ * True if a frame is being requested on the link. |
|
688 |
+ * Used internally by the framework. |
|
689 |
+ */ |
|
690 |
+ unsigned frame_requested; |
|
691 |
+ |
|
692 |
+ /** |
|
693 |
+ * Link processing flags. |
|
694 |
+ */ |
|
695 |
+ unsigned flags; |
|
685 | 696 |
}; |
686 | 697 |
|
687 | 698 |
/** |
... | ... |
@@ -325,4 +325,18 @@ int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef ** |
325 | 325 |
*/ |
326 | 326 |
int ff_filter_frame(AVFilterLink *link, AVFrame *frame); |
327 | 327 |
|
328 |
+/** |
|
329 |
+ * Flags for AVFilterLink.flags. |
|
330 |
+ */ |
|
331 |
+enum { |
|
332 |
+ |
|
333 |
+ /** |
|
334 |
+ * Frame requests may need to loop in order to be fulfilled. |
|
335 |
+ * A filter must set this flags on an output link if it may return 0 in |
|
336 |
+ * request_frame() without filtering a frame. |
|
337 |
+ */ |
|
338 |
+ FF_LINK_FLAG_REQUEST_LOOP = 1, |
|
339 |
+ |
|
340 |
+}; |
|
341 |
+ |
|
328 | 342 |
#endif /* AVFILTER_INTERNAL_H */ |