Commit fdd8aac7 authored by Michael Niedermayer's avatar Michael Niedermayer

avfilter/src_movie: Add option to remove timestamp discontinuities

This can also be extended to remove discontiuities caused by seek commands
Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent d46a8e30
...@@ -16973,6 +16973,11 @@ Default value is "1". ...@@ -16973,6 +16973,11 @@ Default value is "1".
Note that when the movie is looped the source timestamps are not Note that when the movie is looped the source timestamps are not
changed, so it will generate non monotonically increasing timestamps. 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 @end table
It allows overlaying a second video on top of the main input of It allows overlaying a second video on top of the main input of
......
...@@ -48,6 +48,8 @@ typedef struct MovieStream { ...@@ -48,6 +48,8 @@ typedef struct MovieStream {
AVStream *st; AVStream *st;
AVCodecContext *codec_ctx; AVCodecContext *codec_ctx;
int done; int done;
int64_t discontinuity_threshold;
int64_t last_pts;
} MovieStream; } MovieStream;
typedef struct MovieContext { typedef struct MovieContext {
...@@ -60,6 +62,8 @@ typedef struct MovieContext { ...@@ -60,6 +62,8 @@ typedef struct MovieContext {
char *stream_specs; /**< user-provided list of streams, separated by + */ char *stream_specs; /**< user-provided list of streams, separated by + */
int stream_index; /**< for compatibility */ int stream_index; /**< for compatibility */
int loop_count; int loop_count;
int64_t discontinuity_threshold;
int64_t ts_offset;
AVFormatContext *format_ctx; AVFormatContext *format_ctx;
int eof; int eof;
...@@ -84,6 +88,7 @@ static const AVOption movie_options[]= { ...@@ -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 }, { "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 }, { "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 }, { "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 }, { NULL },
}; };
...@@ -282,6 +287,8 @@ static av_cold int movie_common_init(AVFilterContext *ctx) ...@@ -282,6 +287,8 @@ static av_cold int movie_common_init(AVFilterContext *ctx)
st->discard = AVDISCARD_DEFAULT; st->discard = AVDISCARD_DEFAULT;
movie->st[i].st = st; movie->st[i].st = st;
movie->max_stream_index = FFMAX(movie->max_stream_index, st->index); 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)) if (av_strtok(NULL, "+", &cursor))
return AVERROR_BUG; return AVERROR_BUG;
...@@ -549,6 +556,21 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) ...@@ -549,6 +556,21 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
} }
frame->pts = av_frame_get_best_effort_timestamp(frame); 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, 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)); describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment