Fix the segfault in trac ticket #4884. Signed-off-by: Nicolas George <geo...@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. + +@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel