[FFmpeg-devel] [PATCH] lavd/lavfi: add shortest option

Stefano Sabatini stefasab at gmail.com
Fri Jun 1 18:43:31 CEST 2012


---
 doc/indevs.texi     |    5 +++++
 libavdevice/lavfi.c |   32 +++++++++++++++++++++++++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/doc/indevs.texi b/doc/indevs.texi
index e699e11..88f2d44 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -254,6 +254,11 @@ label, but all the others need to be specified explicitly.
 
 If not specified defaults to the filename specified for the input
 device.
+
+ at item shortest
+If set to 1, signal the end when the shortest input ends. If set to 0,
+will continue to output frames until the last stream is ended.
+Default value is 1.
 @end table
 
 @subsection Examples
diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index bdc5f58..790df1e 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -47,6 +47,9 @@ typedef struct {
     AVFilterContext **sinks;
     int *sink_stream_map;
     int *stream_sink_map;
+    int shortest;
+    int *stream_is_ended;
+    int stream_is_ended_count;
 } LavfiContext;
 
 static int *create_all_formats(int n)
@@ -73,6 +76,7 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx)
 
     av_freep(&lavfi->sink_stream_map);
     av_freep(&lavfi->stream_sink_map);
+    av_freep(&lavfi->stream_is_ended);
     av_freep(&lavfi->sinks);
     avfilter_graph_free(&lavfi->graph);
 
@@ -122,6 +126,9 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
         FAIL(AVERROR(ENOMEM));
     if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n)))
         FAIL(AVERROR(ENOMEM));
+    if (!(lavfi->stream_is_ended = av_mallocz(sizeof(int) * n)))
+        FAIL(AVERROR(ENOMEM));
+    lavfi->stream_is_ended_count = 0;
 
     for (i = 0; i < n; i++)
         lavfi->stream_sink_map[i] = -1;
@@ -287,15 +294,33 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     int ret, i;
     int size = 0;
 
+    if (lavfi->stream_is_ended_count == avctx->nb_streams ||
+        (lavfi->stream_is_ended_count && lavfi->shortest))
+        return AVERROR_EOF;
+
     /* iterate through all the graph sinks. Select the sink with the
      * minimum PTS */
     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->stream_is_ended[i])
+            continue;
+        ret = av_buffersink_get_buffer_ref(lavfi->sinks[i], &ref, AV_BUFFERSINK_FLAG_PEEK);
+
+        if (ret == AVERROR_EOF) {
+            lavfi->stream_is_ended[i] = 1;
+            lavfi->stream_is_ended_count++;
+            if (lavfi->stream_is_ended_count == avctx->nb_streams)
+                return ret;
+            else
+                continue;
+        } else if (ret < 0) {
+            char buf[128];
+            av_strerror(ret, buf, sizeof(buf));
+            av_log(avctx, AV_LOG_ERROR, "Error occurred with stream %d: %s\n", i, buf);
             return ret;
+        }
         d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
         av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
 
@@ -344,6 +369,7 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
 static const AVOption options[] = {
     { "graph", "Libavfilter graph", OFFSET(graph_str),  AV_OPT_TYPE_STRING, {.str = NULL }, 0,  0, DEC },
     { "dumpgraph", "Dump graph to stderr", OFFSET(dump_graph), AV_OPT_TYPE_STRING, {.str = NULL}, 0,  0, DEC },
+    { "shortest", "signal end when the shortest input ends", OFFSET(shortest), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1, DEC },
     { NULL },
 };
 
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list