[Libav-user] How to get the last frame from a filter graph?

Tobias Rapp t.rapp at noa-archive.com
Tue Jan 23 10:48:16 EET 2018


On 23.01.2018 09:12, Corey Taylor wrote:
> On Tue, Jan 23, 2018 at 2:04 AM, Tobias Rapp <t.rapp at noa-archive.com> wrote:
>> Hi,
>>
>> in my application I have problems getting the last frame out of a filter
>> graph when the filter chain includes the yadif filter. The application is
>> based on the filtering_video.c example and I can reproduce it when adding
>> the yadif filter there (see attached file).
>>
>> How can I make sure to always get all the frames out of a filter graph?
> 
> 
> You can call av_buffersrc_add_frame_flags with NULL for the frame
> which will signal the end of stream.
> 
> Then you can loop through av_buffersink_get_frame until it returns
> AVERROR_EOF (or any error).
> 
> The loop would typically be:
> 
> 1. Call av_buffersink_get_frame
> 2. If no error, process frame
> 3. if AVERROR_EOF, end your stream

I added a loop to drain the filtergraph (see attached diff) and indeed 
it worked. Maybe I will post a patch to update the upstream example.

> avcodec_send_frame will do the same with a NULL for the frame to
> trigger flushing the codec the same as the filter graph.

Good to know. Thanks a lot for the help!

Regards,
Tobias
-------------- next part --------------
diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c
index 3fd6d5b..4f43ecd 100644
--- a/doc/examples/filtering_video.c
+++ b/doc/examples/filtering_video.c
@@ -278,6 +278,25 @@ int main(int argc, char **argv)
         }
         av_packet_unref(&packet);
     }
+    if (ret == AVERROR_EOF) {
+        /* signal EOF to the filtergraph */
+        if (av_buffersrc_add_frame_flags(buffersrc_ctx, NULL, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
+            goto end;
+        }
+
+        /* pull remaining frames from the filtergraph */
+        while (1) {
+            ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
+            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                break;
+            if (ret < 0)
+                goto end;
+            display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
+            frame_count++;
+            av_frame_unref(filt_frame);
+        }
+    }
     av_log(NULL, AV_LOG_INFO, "Processed %d frames\n", frame_count);
 
 end:


More information about the Libav-user mailing list