diff options
-rw-r--r-- | player/video.c | 12 | ||||
-rw-r--r-- | video/filter/vf.c | 20 | ||||
-rw-r--r-- | video/filter/vf.h | 5 | ||||
-rw-r--r-- | video/filter/vf_dlopen.c | 3 | ||||
-rw-r--r-- | video/filter/vf_lavfi.c | 2 | ||||
-rw-r--r-- | video/filter/vf_softpulldown.c | 3 | ||||
-rw-r--r-- | video/filter/vf_vapoursynth.c | 3 | ||||
-rw-r--r-- | video/filter/vf_vavpp.c | 2 |
8 files changed, 39 insertions, 11 deletions
diff --git a/player/video.c b/player/video.c index 8c607a7036..b995ed2575 100644 --- a/player/video.c +++ b/player/video.c @@ -301,12 +301,12 @@ void mp_force_video_refresh(struct MPContext *mpctx) queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->last_vo_pts, 1, true); } -static bool filter_output_queued_frame(struct MPContext *mpctx) +static bool filter_output_queued_frame(struct MPContext *mpctx, bool eof) { struct dec_video *d_video = mpctx->d_video; struct vo *video_out = mpctx->video_out; - struct mp_image *img = vf_output_queued_frame(d_video->vfilter); + struct mp_image *img = vf_output_queued_frame(d_video->vfilter, eof); if (img) vo_queue_image(video_out, img); talloc_free(img); @@ -316,9 +316,11 @@ static bool filter_output_queued_frame(struct MPContext *mpctx) static bool load_next_vo_frame(struct MPContext *mpctx, bool eof) { - if (vo_get_buffered_frame(mpctx->video_out, eof) >= 0) + if (vo_get_buffered_frame(mpctx->video_out, false) >= 0) return true; - if (filter_output_queued_frame(mpctx)) + if (filter_output_queued_frame(mpctx, eof)) + return true; + if (eof && vo_get_buffered_frame(mpctx->video_out, true) >= 0) return true; return false; } @@ -366,7 +368,7 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame, mp_image_set_params(frame, &d_video->vf_input); // force csp/aspect overrides vf_filter_frame(d_video->vfilter, frame); - filter_output_queued_frame(mpctx); + filter_output_queued_frame(mpctx, false); } // Reconfigure the video chain and the VO on a format change. This is separate, diff --git a/video/filter/vf.c b/video/filter/vf.c index 0d8f239721..021a0e21ae 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -363,14 +363,17 @@ static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf) static int vf_do_filter(struct vf_instance *vf, struct mp_image *img) { assert(vf->fmt_in.imgfmt); - vf_fix_img_params(img, &vf->fmt_in); + if (img) + vf_fix_img_params(img, &vf->fmt_in); if (vf->filter_ext) { return vf->filter_ext(vf, img); } else { - if (vf->filter) - img = vf->filter(vf, img); - vf_add_output_frame(vf, img); + if (img) { + if (vf->filter) + img = vf->filter(vf, img); + vf_add_output_frame(vf, img); + } return 0; } } @@ -379,6 +382,7 @@ static int vf_do_filter(struct vf_instance *vf, struct mp_image *img) // Return >= 0 on success, < 0 on failure (even if output frames were produced) int vf_filter_frame(struct vf_chain *c, struct mp_image *img) { + assert(img); if (c->initialized < 1) { talloc_free(img); return -1; @@ -387,13 +391,19 @@ int vf_filter_frame(struct vf_chain *c, struct mp_image *img) } // Output the next queued image (if any) from the full filter chain. -struct mp_image *vf_output_queued_frame(struct vf_chain *c) +// eof: if set, assume there's no more input i.e. vf_filter_frame() will +// not be called (until reset) - flush all internally delayed frames +struct mp_image *vf_output_queued_frame(struct vf_chain *c, bool eof) { if (c->initialized < 1) return NULL; while (1) { struct vf_instance *last = NULL; for (struct vf_instance * cur = c->first; cur; cur = cur->next) { + // Flush remaining frames on EOF, but do that only if the previous + // filters have been flushed (i.e. they have no more output). + if (eof && !last) + vf_do_filter(cur, NULL); if (cur->num_out_queued) last = cur; } diff --git a/video/filter/vf.h b/video/filter/vf.h index d11c6de575..8e73c69256 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -70,6 +70,9 @@ typedef struct vf_instance { // Like filter(), but can return an error code ( >= 0 means success). This // callback is also more practical when the filter can return multiple // output images. Use vf_add_output_frame() to queue output frames. + // Warning: this is called with mpi==NULL if there is no more input at + // all (i.e. the video has reached end of file condition). This + // can be used to output delayed or otherwise remaining images. int (*filter_ext)(struct vf_instance *vf, struct mp_image *mpi); void (*uninit)(struct vf_instance *vf); @@ -133,7 +136,7 @@ int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params); int vf_control_any(struct vf_chain *c, int cmd, void *arg); int vf_control_by_label(struct vf_chain *c, int cmd, void *arg, bstr label); int vf_filter_frame(struct vf_chain *c, struct mp_image *img); -struct mp_image *vf_output_queued_frame(struct vf_chain *c); +struct mp_image *vf_output_queued_frame(struct vf_chain *c, bool eof); void vf_seek_reset(struct vf_chain *c); struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name, char **args); diff --git a/video/filter/vf_dlopen.c b/video/filter/vf_dlopen.c index 4eefec150c..70c2c6cf24 100644 --- a/video/filter/vf_dlopen.c +++ b/video/filter/vf_dlopen.c @@ -225,6 +225,9 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi) { int i, k; + if (!mpi) + return 0; + set_imgprop(&vf->priv->filter.inpic, mpi); if (mpi->qscale) { if (mpi->qscale_type != 0) { diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c index b100763e05..8e446cec1d 100644 --- a/video/filter/vf_lavfi.c +++ b/video/filter/vf_lavfi.c @@ -251,6 +251,8 @@ static int query_format(struct vf_instance *vf, unsigned int fmt) static AVFrame *mp_to_av(struct vf_instance *vf, struct mp_image *img) { struct vf_priv_s *p = vf->priv; + if (!img) + return NULL; uint64_t pts = img->pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : img->pts * av_q2d(av_inv_q(p->timebase_in)); AVFrame *frame = mp_image_to_av_frame_and_unref(img); diff --git a/video/filter/vf_softpulldown.c b/video/filter/vf_softpulldown.c index eeb2f1c863..afa6bf31f0 100644 --- a/video/filter/vf_softpulldown.c +++ b/video/filter/vf_softpulldown.c @@ -54,6 +54,9 @@ static int filter(struct vf_instance *vf, struct mp_image *mpi) int state = vf->priv->state; struct vf_priv_s *p = vf->priv; + if (!mpi) + return 0; + if (!p->buffer || p->buffer->w != mpi->w || p->buffer->h != mpi->h || p->buffer->imgfmt != mpi->imgfmt) { diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 313b66e26b..a6cf471583 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -180,6 +180,9 @@ static int filter_ext(struct vf_instance *vf, struct mp_image *mpi) if (!p->out_node) return -1; + if (!mpi) + return 0; + // Try to get new frames until we get rid of the input mpi. pthread_mutex_lock(&p->lock); while (1) { diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index 9a797990eb..4b6322cbe2 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -222,6 +222,8 @@ static struct mp_image *upload(struct vf_instance *vf, struct mp_image *in) static int filter_ext(struct vf_instance *vf, struct mp_image *in) { struct vf_priv_s *p = vf->priv; + if (!in) + return 0; int rt_format = in->imgfmt == IMGFMT_VAAPI ? va_surface_rt_format(in) : VA_RT_FORMAT_YUV420; if (!p->pool || p->current_rt_format != rt_format) { |