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.
This commit is contained in:
Uoti Urpala 2009-01-14 02:51:24 +02:00
parent 1f782eb802
commit 38a76f7fdf
4 changed files with 82 additions and 61 deletions

View File

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

View File

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

View File

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

126
mplayer.c
View File

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