[FFmpeg-devel] [PATCH] lavfi/movie: check for format change more carefully.
Nicolas George
george at nsup.org
Wed Sep 30 17:35:55 CEST 2015
Fix the segfault in trac ticket #4884.
Signed-off-by: Nicolas George <george at nsup.org>
---
doc/filters.texi | 8 ++++++++
libavfilter/src_movie.c | 50 +++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index a4d828e..9ad5db9 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -13953,6 +13953,14 @@ 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.
+
+ at item allow_format_change
+Allow format change in the streams. Format changes are normally not
+supported in filters, but a few filters, scale for example unoficially
+support them. If this option is not enabled, changes in format will result
+in a filtering error; if it is enabled, the check is bypassed. If the next
+filter does not support format changes, the behaviour is undefined, a crash
+is possible; use with extreme care.
@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 bbdcbc8..fc2e07d 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -59,6 +59,7 @@ typedef struct MovieContext {
char *stream_specs; /**< user-provided list of streams, separated by + */
int stream_index; /**< for compatibility */
int loop_count;
+ int allow_format_change;
AVFormatContext *format_ctx;
int eof;
@@ -83,6 +84,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 },
+ { "allow_format_change", "allow format change", OFFSET(allow_format_change), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
{ NULL },
};
@@ -539,14 +541,46 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
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));
- if (st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if (frame->format != outlink->format) {
- av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n",
- av_get_pix_fmt_name(outlink->format),
- av_get_pix_fmt_name(frame->format)
- );
- av_frame_free(&frame);
- return 0;
+ if (!movie->allow_format_change) {
+ switch (st->st->codec->codec_type) {
+
+ case AVMEDIA_TYPE_VIDEO:
+ if (frame->width != outlink->w ||
+ frame->height != outlink->h ||
+ frame->format != outlink->format) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Format change: %dx%d/%s -> %dx%d/%s, not supported\n",
+ outlink->w, outlink->h,
+ av_get_pix_fmt_name(outlink->format),
+ frame->width, frame->height,
+ av_get_pix_fmt_name(frame->format));
+ av_frame_free(&frame);
+ return AVERROR_PATCHWELCOME;
+ }
+ break;
+
+ case AVMEDIA_TYPE_AUDIO:
+ if (frame->format != outlink->format ||
+ frame->sample_rate != outlink->sample_rate ||
+ frame->channel_layout != outlink->channel_layout ||
+ av_frame_get_channels(frame) != outlink->channels ) {
+ char l1[128], l2[128];
+ av_get_channel_layout_string(l1, sizeof(l1),
+ outlink->channels,
+ outlink->channel_layout);
+ av_get_channel_layout_string(l2, sizeof(l2),
+ av_frame_get_channels(frame),
+ frame->channel_layout);
+ av_log(ctx, AV_LOG_ERROR,
+ "Format change: %dHz/%s/%s -> %dHz/%s/%s, not supported\n",
+ outlink->sample_rate, l1,
+ av_get_sample_fmt_name(outlink->format),
+ frame->sample_rate, l2,
+ av_get_sample_fmt_name(frame->format));
+ av_frame_free(&frame);
+ return AVERROR_PATCHWELCOME;
+ }
+ break;
}
}
ret = ff_filter_frame(outlink, frame);
--
2.5.3
More information about the ffmpeg-devel
mailing list