Browse code

lavfi: loop on request_frame if necessary.

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.

Nicolas George authored on 2013/04/01 02:17:57
Showing 3 changed files
... ...
@@ -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 */