summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-08-18 20:37:25 +0200
committerwm4 <wm4@nowhere>2016-08-18 20:37:25 +0200
commit7bba97b301c732fb1eb4dad891d00c947d2f6363 (patch)
tree8089058d22204d8009259142d8564b7684467ab7
parent0a0967f48b23a20dce393ec5983b46bb6b361971 (diff)
downloadmpv-7bba97b301c732fb1eb4dad891d00c947d2f6363.tar.bz2
mpv-7bba97b301c732fb1eb4dad891d00c947d2f6363.tar.xz
video: don't discard video frames after endpts
Instead of letting it keep decoding by trying to find a new frame, "plug" the frame queue by not removing it. (Or actually, by putting it back instead of discarding it.) Matters for seamless looping (following commits), and possibly some other corner cases. The added function vf_unread_output_frame() is a bit of a sin, but still reasonable, since its implementation is trivial.
-rw-r--r--player/video.c8
-rw-r--r--video/filter/vf.c7
-rw-r--r--video/filter/vf.h1
3 files changed, 13 insertions, 3 deletions
diff --git a/player/video.c b/player/video.c
index 23f8eefa33..6373123407 100644
--- a/player/video.c
+++ b/player/video.c
@@ -840,9 +840,11 @@ static int video_output_image(struct MPContext *mpctx)
struct mp_image *img = vf_read_output_frame(vo_c->vf);
if (img) {
double endpts = get_play_end_pts(mpctx);
- if (endpts != MP_NOPTS_VALUE && img->pts >= endpts) {
- r = VD_EOF;
- } else if (mpctx->max_frames == 0) {
+ if ((endpts != MP_NOPTS_VALUE && img->pts >= endpts) ||
+ mpctx->max_frames == 0)
+ {
+ vf_unread_output_frame(vo_c->vf, img);
+ img = NULL;
r = VD_EOF;
} else if (hrseek && mpctx->hrseek_lastframe) {
mp_image_setrefp(&mpctx->saved_frame, img);
diff --git a/video/filter/vf.c b/video/filter/vf.c
index 274ca945a2..b632314426 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -458,6 +458,13 @@ struct mp_image *vf_read_output_frame(struct vf_chain *c)
return vf_dequeue_output_frame(c->last);
}
+// Undo the previous vf_read_output_frame().
+void vf_unread_output_frame(struct vf_chain *c, struct mp_image *img)
+{
+ struct vf_instance *vf = c->last;
+ MP_TARRAY_INSERT_AT(vf, vf->out_queued, vf->num_out_queued, 0, img);
+}
+
// Some filters (vf_vapoursynth) filter on separate threads, and may need new
// input from the decoder, even though the core does not need a new output image
// yet (this is required to get proper pipelining in the filter). If the filter
diff --git a/video/filter/vf.h b/video/filter/vf.h
index 49296fb9b2..901ccead95 100644
--- a/video/filter/vf.h
+++ b/video/filter/vf.h
@@ -157,6 +157,7 @@ int vf_filter_frame(struct vf_chain *c, struct mp_image *img);
int vf_output_frame(struct vf_chain *c, bool eof);
int vf_needs_input(struct vf_chain *c);
struct mp_image *vf_read_output_frame(struct vf_chain *c);
+void vf_unread_output_frame(struct vf_chain *c, struct mp_image *img);
void vf_seek_reset(struct vf_chain *c);
struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name,
char **args);