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.
This commit is contained in:
wm4 2016-08-18 20:37:25 +02:00
parent 0a0967f48b
commit 7bba97b301
3 changed files with 13 additions and 3 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);