diff --git a/doc/filters.texi b/doc/filters.texi index b35c65135c..aa208f1989 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16976,4 +16976,28 @@ movie=dvd.vob:s=v:0+#0x81 [video] [audio] @end example @end itemize +@subsection Commands + +Both movie and amovie support the following commands: +@table @option +@item seek +Perform seek using "av_seek_frame". +The syntax is: seek @var{stream_index}|@var{timestamp}|@var{flags} +@itemize +@item +@var{stream_index}: If stream_index is -1, a default +stream is selected, and @var{timestamp} is automatically converted +from AV_TIME_BASE units to the stream specific time_base. +@item +@var{timestamp}: Timestamp in AVStream.time_base units +or, if no stream is specified, in AV_TIME_BASE units. +@item +@var{flags}: Flags which select direction and seeking mode. +@end itemize + +@item get_duration +Get movie duration in AV_TIME_BASE units. + +@end table + @c man end MULTIMEDIA SOURCES diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 0bdcad4265..9ac115b66e 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -582,6 +582,49 @@ static int movie_request_frame(AVFilterLink *outlink) } } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + MovieContext *movie = ctx->priv; + int ret = AVERROR(ENOSYS); + + if (!strcmp(cmd, "seek")) { + int idx, flags, i; + int64_t ts; + char tail[2]; + + if (sscanf(args, "%i|%"SCNi64"|%i %1s", &idx, &ts, &flags, tail) != 3) + return AVERROR(EINVAL); + + ret = av_seek_frame(movie->format_ctx, idx, ts, flags); + if (ret < 0) + return ret; + + for (i = 0; i < ctx->nb_outputs; i++) { + avcodec_flush_buffers(movie->st[i].codec_ctx); + movie->st[i].done = 0; + } + return ret; + } else if (!strcmp(cmd, "get_duration")) { + int print_len; + char tail[2]; + + if (!res || res_len <= 0) + return AVERROR(EINVAL); + + if (args && sscanf(args, "%1s", tail) == 1) + return AVERROR(EINVAL); + + print_len = snprintf(res, res_len, "%"PRId64, movie->format_ctx->duration); + if (print_len < 0 || print_len >= res_len) + return AVERROR(EINVAL); + + return 0; + } + + return ret; +} + #if CONFIG_MOVIE_FILTER AVFILTER_DEFINE_CLASS(movie); @@ -598,6 +641,7 @@ AVFilter ff_avsrc_movie = { .inputs = NULL, .outputs = NULL, .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .process_command = process_command }; #endif /* CONFIG_MOVIE_FILTER */ @@ -619,6 +663,7 @@ AVFilter ff_avsrc_amovie = { .outputs = NULL, .priv_class = &amovie_class, .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .process_command = process_command, }; #endif /* CONFIG_AMOVIE_FILTER */