[FFmpeg-devel] [PATCH] lavd/lavfi: push frames until the last sink is EOF

Stefano Sabatini stefasab at gmail.com
Thu Sep 20 11:48:18 CEST 2012


Previously the device was returning EOF when the first sink was ending,
with the current change the device will continue to return frames until
all the sinks are EOF, which seems the most expected behavior.
---
 libavdevice/lavfi.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index c75baf9..e080857 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -46,6 +46,7 @@ typedef struct {
     AVFilterGraph *graph;
     AVFilterContext **sinks;
     int *sink_stream_map;
+    int *sink_eof;
     int *stream_sink_map;
 } LavfiContext;
 
@@ -72,6 +73,7 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx)
     LavfiContext *lavfi = avctx->priv_data;
 
     av_freep(&lavfi->sink_stream_map);
+    av_freep(&lavfi->sink_eof);
     av_freep(&lavfi->stream_sink_map);
     av_freep(&lavfi->sinks);
     avfilter_graph_free(&lavfi->graph);
@@ -120,6 +122,8 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
 
     if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n)))
         FAIL(AVERROR(ENOMEM));
+    if (!(lavfi->sink_eof = av_mallocz(sizeof(int) * n)))
+        FAIL(AVERROR(ENOMEM));
     if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n)))
         FAIL(AVERROR(ENOMEM));
 
@@ -284,9 +288,18 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     for (i = 0; i < avctx->nb_streams; i++) {
         AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
         double d;
-        int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
-                                               &ref, AV_BUFFERSINK_FLAG_PEEK);
-        if (ret < 0)
+        int ret;
+
+        if (lavfi->sink_eof[i])
+            continue;
+
+        ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
+                                       &ref, AV_BUFFERSINK_FLAG_PEEK);
+        if (ret == AVERROR_EOF) {
+            av_dlog(avctx, "EOF sink_idx:%d\n", i);
+            lavfi->sink_eof[i] = 1;
+            continue;
+        } else if (ret < 0)
             return ret;
         d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
         av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
@@ -296,6 +309,9 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
             min_pts_sink_idx = i;
         }
     }
+    if (min_pts == DBL_MAX)
+        return AVERROR_EOF;
+
     av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);
 
     av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
@@ -325,7 +341,6 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     pkt->pos = ref->pos;
     pkt->size = size;
     avfilter_unref_buffer(ref);
-
     return size;
 }
 
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list