From 38a76f7fdf5c03bc49072b693d7c53b343f2994a Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Wed, 14 Jan 2009 02:51:24 +0200 Subject: [PATCH] core: Better -nocorrect-pts pause and filter-added frames handling Rewrite the -nocorrect-pts frame creation code. The new version always updates the visible frame when seeking while pausing, and supports filter-added frames. It can not time those properly though. Now the handling of filter-added frames in MPlayer always uses the new method independently of the value of correct-pts but MEncoder still expects the old behavior. Add a global variable that is set under MEncoder only and change the filters to choose behavior based on that instead of the correct_pts option. --- libmpcodecs/vf_tfields.c | 9 +-- libmpcodecs/vf_yadif.c | 7 ++- mencoder.c | 1 + mplayer.c | 126 ++++++++++++++++++++++----------------- 4 files changed, 82 insertions(+), 61 deletions(-) diff --git a/libmpcodecs/vf_tfields.c b/libmpcodecs/vf_tfields.c index 0d88119371..347cd4bb9e 100644 --- a/libmpcodecs/vf_tfields.c +++ b/libmpcodecs/vf_tfields.c @@ -310,9 +310,10 @@ static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts) return continue_buffered_image(vf); } +extern const int under_mencoder; + static int continue_buffered_image(struct vf_instance *vf) { - struct MPOpts *opts = vf->opts; int i=vf->priv->buffered_i; double pts = vf->priv->buffered_pts; mp_image_t *mpi = vf->priv->buffered_mpi; @@ -363,7 +364,7 @@ static int continue_buffered_image(struct vf_instance *vf) dmpi->stride[2] = 2*mpi->stride[2]; } ret |= vf_next_put_image(vf, dmpi, pts); - if (opts->correct_pts) + if (!under_mencoder) break; else if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL); @@ -393,7 +394,7 @@ static int continue_buffered_image(struct vf_instance *vf) mpi->chroma_width, mpi->chroma_height, (i^!tff)); } ret |= vf_next_put_image(vf, dmpi, pts); - if (opts->correct_pts) + if (!under_mencoder) break; else if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL); @@ -419,7 +420,7 @@ static int continue_buffered_image(struct vf_instance *vf) dmpi->stride[2], mpi->stride[2]*2, (i^!tff)); } ret |= vf_next_put_image(vf, dmpi, pts); - if (opts->correct_pts) + if (!under_mencoder) break; else if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL); diff --git a/libmpcodecs/vf_yadif.c b/libmpcodecs/vf_yadif.c index fd46f241cd..2c80a2ec5b 100644 --- a/libmpcodecs/vf_yadif.c +++ b/libmpcodecs/vf_yadif.c @@ -416,9 +416,10 @@ static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts){ return continue_buffered_image(vf); } +extern const int under_mencoder; + static int continue_buffered_image(struct vf_instance *vf) { - struct MPOpts *opts = vf->opts; mp_image_t *mpi = vf->priv->buffered_mpi; int tff = vf->priv->buffered_tff; double pts = vf->priv->buffered_pts; @@ -435,10 +436,10 @@ static int continue_buffered_image(struct vf_instance *vf) mpi->width,mpi->height); vf_clone_mpi_attributes(dmpi, mpi); filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff); - if (opts->correct_pts && i < (vf->priv->mode & 1)) + if (i < (vf->priv->mode & 1) && !under_mencoder) vf_queue_frame(vf, continue_buffered_image); ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/); - if (opts->correct_pts) + if (!under_mencoder) break; if(i<(vf->priv->mode&1)) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL); diff --git a/mencoder.c b/mencoder.c index 052cfdbcde..52edeeac88 100644 --- a/mencoder.c +++ b/mencoder.c @@ -96,6 +96,7 @@ MPOpts opts; struct osd_state *osd; +const int under_mencoder = 1; int vo_doublebuffering=0; int vo_directrendering=0; int forced_subs_only=0; diff --git a/mplayer.c b/mplayer.c index ac53ed4abb..2ece0607ef 100644 --- a/mplayer.c +++ b/mplayer.c @@ -87,6 +87,7 @@ #include "input/input.h" +const int under_mencoder = 0; int slave_mode=0; int player_idle_mode=0; int quiet=0; @@ -2209,65 +2210,82 @@ err_out: return 0; } +static double update_video_nocorrect_pts(struct MPContext *mpctx, + int *blit_frame) +{ + struct sh_video *sh_video = mpctx->sh_video; + *blit_frame = 0; + double frame_time = 0; + while (1) { + current_module = "filter_video"; + // In nocorrect-pts mode there is no way to properly time these frames + if (vf_output_queued_frame(sh_video->vfilter)) + break; + unsigned char *packet = NULL; + frame_time = sh_video->next_frame_time; + if (mpctx->update_video_immediately) + frame_time = 0; + int in_size = video_read_frame(sh_video, &sh_video->next_frame_time, + &packet, force_fps); + if (in_size < 0) { +#ifdef CONFIG_DVDNAV + if (mpctx->stream->type == STREAMTYPE_DVDNAV) { + if (mp_dvdnav_is_eof(mpctx->stream)) + return -1; + if (mpctx->d_video) + mpctx->d_video->eof = 0; + if (mpctx->d_audio) + mpctx->d_audio->eof = 0; + mpctx->stream->eof = 0; + } else +#endif + return -1; + } + if (in_size > max_framesize) + max_framesize = in_size; + sh_video->timer += frame_time; + if (mpctx->sh_audio) + mpctx->delay -= frame_time; + // video_read_frame can change fps (e.g. for ASF video) + vo_fps = sh_video->fps; + int framedrop_type = check_framedrop(mpctx, frame_time); + current_module = "decode video"; + + void *decoded_frame; +#ifdef CONFIG_DVDNAV + decoded_frame = mp_dvdnav_restore_smpi(mpctx, &in_size, &packet, NULL); + if (in_size >= 0 && !decoded_frame) +#endif + decoded_frame = decode_video(sh_video, packet, in_size, framedrop_type, + sh_video->pts); +#ifdef CONFIG_DVDNAV + // Save last still frame for future display + mp_dvdnav_restore_smpi(mpctx, in_size, packet, decoded_frame); +#endif + if (decoded_frame) { + // These updates are done here for vf_expand OSD/subtitles + update_subtitles(sh_video, mpctx->d_sub, 0); + update_teletext(sh_video, mpctx->demuxer, 0); + update_osd_msg(mpctx); + current_module = "filter video"; + if (filter_video(sh_video, decoded_frame, sh_video->pts, + mpctx->osd)) + break; + } + } + *blit_frame = 1; + return frame_time; +} + static double update_video(struct MPContext *mpctx, int *blit_frame) { - struct MPOpts *opts = &mpctx->opts; - sh_video_t * const sh_video = mpctx->sh_video; - //-------------------- Decode a frame: ----------------------- + struct sh_video *sh_video = mpctx->sh_video; double frame_time; - *blit_frame = 0; // Don't blit if we hit EOF + *blit_frame = 0; sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ, mpctx->osd); // hack for vf_expand - if (!opts->correct_pts) { - unsigned char* start=NULL; - void *decoded_frame = NULL; - int drop_frame=0; - int in_size; - - current_module = "video_read_frame"; - frame_time = sh_video->next_frame_time; - in_size = video_read_frame(sh_video, &sh_video->next_frame_time, - &start, force_fps); -#ifdef CONFIG_DVDNAV - /// wait, still frame or EOF - if (mpctx->stream->type == STREAMTYPE_DVDNAV && in_size < 0) { - if (mp_dvdnav_is_eof(mpctx->stream)) return -1; - if (mpctx->d_video) mpctx->d_video->eof = 0; - if (mpctx->d_audio) mpctx->d_audio->eof = 0; - mpctx->stream->eof = 0; - } else -#endif - if (in_size < 0) - return -1; - if (in_size > max_framesize) - max_framesize = in_size; // stats - sh_video->timer += frame_time; - if (mpctx->sh_audio) - mpctx->delay -= frame_time; - // video_read_frame can change fps (e.g. for ASF video) - vo_fps = sh_video->fps; - drop_frame = check_framedrop(mpctx, frame_time); - update_subtitles(sh_video, mpctx->d_sub, 0); - update_teletext(sh_video, mpctx->demuxer, 0); - update_osd_msg(mpctx); - current_module = "decode_video"; -#ifdef CONFIG_DVDNAV - decoded_frame = mp_dvdnav_restore_smpi(mpctx, &in_size,&start, - decoded_frame); - /// still frame has been reached, no need to decode - if (in_size > 0 && !decoded_frame) -#endif - decoded_frame = decode_video(sh_video, start, in_size, drop_frame, - sh_video->pts); -#ifdef CONFIG_DVDNAV - /// save back last still frame for future display - mp_dvdnav_save_smpi(mpctx, in_size, start, decoded_frame); -#endif - current_module = "filter_video"; - *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, - sh_video->pts, - mpctx->osd)); - } + if (!mpctx->opts.correct_pts) + return update_video_nocorrect_pts(mpctx, blit_frame); else { int res = generate_video_frame(mpctx); if (!res)