diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2016-05-25 17:55:29 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2016-06-26 00:20:00 +0200 |
commit | fdd8aac7e12e25f1007afd97ec26297be6f4422e (patch) | |
tree | d7e62ebda2ff50b6427fa6978a9679f85b169342 | |
parent | d46a8e30dcacd0e9aeb1c19239ee1e0808801cb5 (diff) | |
download | ffmpeg-fdd8aac7e12e25f1007afd97ec26297be6f4422e.tar.gz |
avfilter/src_movie: Add option to remove timestamp discontinuities
This can also be extended to remove discontiuities caused by seek commands
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r-- | doc/filters.texi | 5 | ||||
-rw-r--r-- | libavfilter/src_movie.c | 22 |
2 files changed, 27 insertions, 0 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index 7267b21874..3cf3d7ce89 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16973,6 +16973,11 @@ 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. + +@item discontinuity +Specifies the time difference between frames above which the point is +considered a timestamp discontinuity which is removed by adjusting the later +timestamps. @end table It allows overlaying a second video on top of the main input of diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 4714ca9549..23dcb7ba2e 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -48,6 +48,8 @@ typedef struct MovieStream { AVStream *st; AVCodecContext *codec_ctx; int done; + int64_t discontinuity_threshold; + int64_t last_pts; } MovieStream; typedef struct MovieContext { @@ -60,6 +62,8 @@ typedef struct MovieContext { char *stream_specs; /**< user-provided list of streams, separated by + */ int stream_index; /**< for compatibility */ int loop_count; + int64_t discontinuity_threshold; + int64_t ts_offset; AVFormatContext *format_ctx; int eof; @@ -84,6 +88,7 @@ static const AVOption movie_options[]= { { "streams", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, FLAGS }, { "s", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, FLAGS }, { "loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, FLAGS }, + { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS }, { NULL }, }; @@ -282,6 +287,8 @@ static av_cold int movie_common_init(AVFilterContext *ctx) st->discard = AVDISCARD_DEFAULT; movie->st[i].st = st; movie->max_stream_index = FFMAX(movie->max_stream_index, st->index); + movie->st[i].discontinuity_threshold = + av_rescale_q(movie->discontinuity_threshold, AV_TIME_BASE_Q, st->time_base); } if (av_strtok(NULL, "+", &cursor)) return AVERROR_BUG; @@ -549,6 +556,21 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) } frame->pts = av_frame_get_best_effort_timestamp(frame); + if (frame->pts != AV_NOPTS_VALUE) { + if (movie->ts_offset) + frame->pts += av_rescale_q_rnd(movie->ts_offset, AV_TIME_BASE_Q, outlink->time_base, AV_ROUND_UP); + if (st->discontinuity_threshold) { + if (st->last_pts != AV_NOPTS_VALUE) { + int64_t diff = frame->pts - st->last_pts; + if (diff < 0 || diff > st->discontinuity_threshold) { + av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", pkt_out_id, diff); + movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP); + frame->pts -= diff; + } + } + } + st->last_pts = frame->pts; + } ff_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink)); |