summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/video.c12
-rw-r--r--video/filter/vf.c20
-rw-r--r--video/filter/vf.h5
-rw-r--r--video/filter/vf_dlopen.c3
-rw-r--r--video/filter/vf_lavfi.c2
-rw-r--r--video/filter/vf_softpulldown.c3
-rw-r--r--video/filter/vf_vapoursynth.c3
-rw-r--r--video/filter/vf_vavpp.c2
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) {