From: Clément Bœsch <clem...@stupeflix.com> --- doc/ffplay.texi | 3 +++ ffplay.c | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/doc/ffplay.texi b/doc/ffplay.texi index 45731a2..126c19b 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -174,6 +174,9 @@ input as soon as possible. Enabled by default for realtime streams, where data may be dropped if not read in time. Use this option to enable infinite buffers for all inputs, use @option{-noinfbuf} to disable it. +@item -honor_timeline +Enable support for format timelines such as MOV/MP4 edit lists. Enabled by +default, use @option{-nohonor_timeline} to disable it. @end table @section While playing diff --git a/ffplay.c b/ffplay.c index 72ec35d..0e70f25 100644 --- a/ffplay.c +++ b/ffplay.c @@ -342,6 +342,7 @@ static int nb_vfilters = 0; static char *afilters = NULL; #endif static int autorotate = 1; +static int honor_timeline = 1; /* current context */ static int is_full_screen; @@ -2022,6 +2023,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c } } + if (honor_timeline && + (ret = insert_timeline_graph(is->video_st, &last_filter, 0, 1)) < 0) + goto fail; + if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0) goto fail; @@ -2038,7 +2043,7 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for int sample_rates[2] = { 0, -1 }; int64_t channel_layouts[2] = { 0, -1 }; int channels[2] = { 0, -1 }; - AVFilterContext *filt_asrc = NULL, *filt_asink = NULL; + AVFilterContext *filt_asrc = NULL, *filt_asink = NULL, *last_filter = NULL; char aresample_swr_opts[512] = ""; AVDictionaryEntry *e = NULL; char asrc_args[256]; @@ -2095,8 +2100,14 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for goto end; } + last_filter = filt_asink; - if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0) + // XXX: audio stream can be NULL here, why? + if (honor_timeline && is->audio_st && + (ret = insert_timeline_graph(is->audio_st, &last_filter, 0, 1)) < 0) + goto end; + + if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, last_filter)) < 0) goto end; is->in_audio_filter = filt_asrc; @@ -2880,7 +2891,7 @@ static int read_thread(void *arg) AVDictionary **opts; int orig_nb_streams; SDL_mutex *wait_mutex = SDL_CreateMutex(); - int scan_all_pmts_set = 0; + int scan_all_pmts_set = 0, ignore_editlist_set = 0; memset(st_index, -1, sizeof(st_index)); is->last_video_stream = is->video_stream = -1; @@ -2894,6 +2905,11 @@ static int read_thread(void *arg) av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE); scan_all_pmts_set = 1; } + if (CONFIG_AVFILTER && honor_timeline && + !av_dict_get(format_opts, "ignore_editlist", NULL, AV_DICT_MATCH_CASE)) { + av_dict_set(&format_opts, "ignore_editlist", "export", AV_DICT_DONT_OVERWRITE); + ignore_editlist_set = 1; + } err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts); if (err < 0) { print_error(is->filename, err); @@ -2902,6 +2918,8 @@ static int read_thread(void *arg) } if (scan_all_pmts_set) av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE); + if (ignore_editlist_set) + av_dict_set(&format_opts, "ignore_editlist", NULL, AV_DICT_MATCH_CASE); if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key); @@ -3713,6 +3731,7 @@ static const OptionDef options[] = { { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" }, { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" }, { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" }, + { "honor_timeline", OPT_BOOL | OPT_EXPERT, { &honor_timeline }, "honor timelines", "" }, { NULL, }, }; -- 2.2.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel