summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/filters.texi7
-rw-r--r--libavfilter/src_movie.c28
-rw-r--r--libavfilter/version.h2
3 files changed, 31 insertions, 6 deletions
diff --git a/doc/filters.texi b/doc/filters.texi
index 0a6af0530f..9aedb01bb2 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -3104,6 +3104,13 @@ Specifies the index of the video stream to read. If the value is -1,
the best suited video stream will be automatically selected. Default
value is "-1".
+@item loop
+Specifies how many times to read the video stream in sequence.
+If the value is less than 1, the stream will be read again and again.
+Default value is "1".
+
+Note that when the movie is looped the source timestamps are not
+changed, so it will generate non monotonically increasing timestamps.
@end table
This filter allows to overlay a second video on top of main input of
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index a0b427d82c..1d65ade5c8 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -46,6 +46,7 @@ typedef struct {
char *format_name;
char *file_name;
int stream_index;
+ int loop_count;
AVFormatContext *format_ctx;
AVCodecContext *codec_ctx;
@@ -71,6 +72,7 @@ static const AVOption movie_options[]= {
{"si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX },
{"seek_point", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, (INT64_MAX-1) / 1000000 },
{"sp", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, (INT64_MAX-1) / 1000000 },
+{"loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.dbl = 1}, 0, INT_MAX },
{NULL},
};
@@ -245,7 +247,27 @@ static int movie_get_frame(AVFilterLink *outlink)
if (movie->is_done == 1)
return 0;
- while ((ret = av_read_frame(movie->format_ctx, &pkt)) >= 0) {
+ while (1) {
+ ret = av_read_frame(movie->format_ctx, &pkt);
+ if (ret == AVERROR_EOF) {
+ int64_t timestamp;
+ if (movie->loop_count != 1) {
+ timestamp = movie->seek_point;
+ if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
+ timestamp += movie->format_ctx->start_time;
+ if (av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD) < 0) {
+ movie->is_done = 1;
+ break;
+ } else if (movie->loop_count>1)
+ movie->loop_count--;
+ continue;
+ } else {
+ movie->is_done = 1;
+ break;
+ }
+ } else if (ret < 0)
+ break;
+
// Is this a packet from the video stream?
if (pkt.stream_index == movie->stream_index) {
avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt);
@@ -284,10 +306,6 @@ static int movie_get_frame(AVFilterLink *outlink)
av_free_packet(&pkt);
}
- // On multi-frame source we should stop the mixing process when
- // the movie source does not have more frames
- if (ret == AVERROR_EOF)
- movie->is_done = 1;
return ret;
}
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 50c48d9dda..2a85b2c60a 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 65
-#define LIBAVFILTER_VERSION_MICRO 100
+#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \