From 2f69e8f93c468242c866f82b51d4725bcf7d18f2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 3 Jan 2015 03:01:58 +0100 Subject: video: better pipelining with vf_vapoursynth Most of this is explained in the code comments. This change should improve performance with vapoursynth, especially if concurrent requests are used. This should change nothing if vf_vapoursynth is not in the filter chain, since non-threaded filters obviously can not asynchronously finish filtering of frames. --- player/core.h | 1 + player/main.c | 2 +- player/video.c | 27 ++++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'player') diff --git a/player/core.h b/player/core.h index 4c8b067bb7..c663a046c7 100644 --- a/player/core.h +++ b/player/core.h @@ -398,6 +398,7 @@ int mp_initialize(struct MPContext *mpctx); struct MPContext *mp_create(void); void mp_destroy(struct MPContext *mpctx); void mp_print_version(struct mp_log *log, int always); +void wakeup_playloop(void *ctx); // misc.c double get_start_time(struct MPContext *mpctx); diff --git a/player/main.c b/player/main.c index e9820b2afe..c94c53225b 100644 --- a/player/main.c +++ b/player/main.c @@ -368,7 +368,7 @@ struct MPContext *mp_create(void) return mpctx; } -static void wakeup_playloop(void *ctx) +void wakeup_playloop(void *ctx) { struct MPContext *mpctx = ctx; mp_input_wakeup(mpctx->input); diff --git a/player/video.c b/player/video.c index 55daade37a..49476b7235 100644 --- a/player/video.c +++ b/player/video.c @@ -178,6 +178,8 @@ static void recreate_video_filters(struct MPContext *mpctx) vf_destroy(d_video->vfilter); d_video->vfilter = vf_new(mpctx->global); d_video->vfilter->hwdec = d_video->hwdec_info; + d_video->vfilter->wakeup_callback = wakeup_playloop; + d_video->vfilter->wakeup_callback_ctx = mpctx; vf_append_filter_list(d_video->vfilter, opts->vf_settings); @@ -432,7 +434,8 @@ static int video_filter(struct MPContext *mpctx, bool eof) return VD_ERROR; // There is already a filtered frame available. - if (vf_output_frame(vf, eof) > 0) + // If vf_needs_input() returns > 0, the filter wants input anyway. + if (vf_output_frame(vf, eof) > 0 && vf_needs_input(vf) < 1) return VD_PROGRESS; // Decoder output is different from filter input? @@ -493,6 +496,20 @@ static int video_decode_and_filter(struct MPContext *mpctx) return r; } +static int video_feed_async_filter(struct MPContext *mpctx) +{ + struct dec_video *d_video = mpctx->d_video; + struct vf_chain *vf = d_video->vfilter; + + if (vf->initialized < 0) + return VD_ERROR; + + if (vf_needs_input(vf) < 1) + return 0; + mpctx->sleeptime = 0; // retry until done + return video_decode_and_filter(mpctx); +} + /* Modify video timing to match the audio timeline. There are two main * reasons this is needed. First, video and audio can start from different * positions at beginning of file or after a seek (MPlayer starts both @@ -779,8 +796,12 @@ void write_video(struct MPContext *mpctx, double endpts) double time_frame = MPMAX(mpctx->time_frame, -1); int64_t pts = mp_time_us() + (int64_t)(time_frame * 1e6); - if (!vo_is_ready_for_frame(vo, pts)) - return; // wait until VO wakes us up to get more frames + // wait until VO wakes us up to get more frames + if (!vo_is_ready_for_frame(vo, pts)) { + if (video_feed_async_filter(mpctx) < 0) + goto error; + return; + } int64_t duration = -1; double diff = -1; -- cgit v1.2.3