From d19d52d4a11547cc70bcbc3a2f8b83ccd24bb951 Mon Sep 17 00:00:00 2001 From: William Yu Date: Thu, 15 Mar 2012 19:45:26 +0800 Subject: [PATCH] lavfi/movie: add loop parameter Signed-off-by: William Yu Signed-off-by: Stefano Sabatini --- doc/filters.texi | 7 +++++++ libavfilter/src_movie.c | 28 +++++++++++++++++++++++----- libavfilter/version.h | 2 +- 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, \