mirror of https://github.com/mpv-player/mpv
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:
parent
1f782eb802
commit
38a76f7fdf
|
@ -310,9 +310,10 @@ static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts)
|
||||||
return continue_buffered_image(vf);
|
return continue_buffered_image(vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const int under_mencoder;
|
||||||
|
|
||||||
static int continue_buffered_image(struct vf_instance *vf)
|
static int continue_buffered_image(struct vf_instance *vf)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = vf->opts;
|
|
||||||
int i=vf->priv->buffered_i;
|
int i=vf->priv->buffered_i;
|
||||||
double pts = vf->priv->buffered_pts;
|
double pts = vf->priv->buffered_pts;
|
||||||
mp_image_t *mpi = vf->priv->buffered_mpi;
|
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];
|
dmpi->stride[2] = 2*mpi->stride[2];
|
||||||
}
|
}
|
||||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||||
if (opts->correct_pts)
|
if (!under_mencoder)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
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));
|
mpi->chroma_width, mpi->chroma_height, (i^!tff));
|
||||||
}
|
}
|
||||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||||
if (opts->correct_pts)
|
if (!under_mencoder)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
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));
|
dmpi->stride[2], mpi->stride[2]*2, (i^!tff));
|
||||||
}
|
}
|
||||||
ret |= vf_next_put_image(vf, dmpi, pts);
|
ret |= vf_next_put_image(vf, dmpi, pts);
|
||||||
if (opts->correct_pts)
|
if (!under_mencoder)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||||
|
|
|
@ -416,9 +416,10 @@ static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts){
|
||||||
return continue_buffered_image(vf);
|
return continue_buffered_image(vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const int under_mencoder;
|
||||||
|
|
||||||
static int continue_buffered_image(struct vf_instance *vf)
|
static int continue_buffered_image(struct vf_instance *vf)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = vf->opts;
|
|
||||||
mp_image_t *mpi = vf->priv->buffered_mpi;
|
mp_image_t *mpi = vf->priv->buffered_mpi;
|
||||||
int tff = vf->priv->buffered_tff;
|
int tff = vf->priv->buffered_tff;
|
||||||
double pts = vf->priv->buffered_pts;
|
double pts = vf->priv->buffered_pts;
|
||||||
|
@ -435,10 +436,10 @@ static int continue_buffered_image(struct vf_instance *vf)
|
||||||
mpi->width,mpi->height);
|
mpi->width,mpi->height);
|
||||||
vf_clone_mpi_attributes(dmpi, mpi);
|
vf_clone_mpi_attributes(dmpi, mpi);
|
||||||
filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff);
|
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);
|
vf_queue_frame(vf, continue_buffered_image);
|
||||||
ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/);
|
ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/);
|
||||||
if (opts->correct_pts)
|
if (!under_mencoder)
|
||||||
break;
|
break;
|
||||||
if(i<(vf->priv->mode&1))
|
if(i<(vf->priv->mode&1))
|
||||||
vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
MPOpts opts;
|
MPOpts opts;
|
||||||
struct osd_state *osd;
|
struct osd_state *osd;
|
||||||
|
|
||||||
|
const int under_mencoder = 1;
|
||||||
int vo_doublebuffering=0;
|
int vo_doublebuffering=0;
|
||||||
int vo_directrendering=0;
|
int vo_directrendering=0;
|
||||||
int forced_subs_only=0;
|
int forced_subs_only=0;
|
||||||
|
|
102
mplayer.c
102
mplayer.c
|
@ -87,6 +87,7 @@
|
||||||
|
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
|
||||||
|
const int under_mencoder = 0;
|
||||||
int slave_mode=0;
|
int slave_mode=0;
|
||||||
int player_idle_mode=0;
|
int player_idle_mode=0;
|
||||||
int quiet=0;
|
int quiet=0;
|
||||||
|
@ -2209,65 +2210,82 @@ err_out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double update_video(struct MPContext *mpctx, int *blit_frame)
|
static double update_video_nocorrect_pts(struct MPContext *mpctx,
|
||||||
|
int *blit_frame)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = &mpctx->opts;
|
struct sh_video *sh_video = mpctx->sh_video;
|
||||||
sh_video_t * const sh_video = mpctx->sh_video;
|
*blit_frame = 0;
|
||||||
//-------------------- Decode a frame: -----------------------
|
double frame_time = 0;
|
||||||
double frame_time;
|
while (1) {
|
||||||
*blit_frame = 0; // Don't blit if we hit EOF
|
current_module = "filter_video";
|
||||||
sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ,
|
// In nocorrect-pts mode there is no way to properly time these frames
|
||||||
mpctx->osd); // hack for vf_expand
|
if (vf_output_queued_frame(sh_video->vfilter))
|
||||||
if (!opts->correct_pts) {
|
break;
|
||||||
unsigned char* start=NULL;
|
unsigned char *packet = NULL;
|
||||||
void *decoded_frame = NULL;
|
|
||||||
int drop_frame=0;
|
|
||||||
int in_size;
|
|
||||||
|
|
||||||
current_module = "video_read_frame";
|
|
||||||
frame_time = sh_video->next_frame_time;
|
frame_time = sh_video->next_frame_time;
|
||||||
in_size = video_read_frame(sh_video, &sh_video->next_frame_time,
|
if (mpctx->update_video_immediately)
|
||||||
&start, force_fps);
|
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
|
#ifdef CONFIG_DVDNAV
|
||||||
/// wait, still frame or EOF
|
if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
|
||||||
if (mpctx->stream->type == STREAMTYPE_DVDNAV && in_size < 0) {
|
if (mp_dvdnav_is_eof(mpctx->stream))
|
||||||
if (mp_dvdnav_is_eof(mpctx->stream)) return -1;
|
return -1;
|
||||||
if (mpctx->d_video) mpctx->d_video->eof = 0;
|
if (mpctx->d_video)
|
||||||
if (mpctx->d_audio) mpctx->d_audio->eof = 0;
|
mpctx->d_video->eof = 0;
|
||||||
|
if (mpctx->d_audio)
|
||||||
|
mpctx->d_audio->eof = 0;
|
||||||
mpctx->stream->eof = 0;
|
mpctx->stream->eof = 0;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (in_size < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (in_size > max_framesize)
|
if (in_size > max_framesize)
|
||||||
max_framesize = in_size; // stats
|
max_framesize = in_size;
|
||||||
sh_video->timer += frame_time;
|
sh_video->timer += frame_time;
|
||||||
if (mpctx->sh_audio)
|
if (mpctx->sh_audio)
|
||||||
mpctx->delay -= frame_time;
|
mpctx->delay -= frame_time;
|
||||||
// video_read_frame can change fps (e.g. for ASF video)
|
// video_read_frame can change fps (e.g. for ASF video)
|
||||||
vo_fps = sh_video->fps;
|
vo_fps = sh_video->fps;
|
||||||
drop_frame = check_framedrop(mpctx, frame_time);
|
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_subtitles(sh_video, mpctx->d_sub, 0);
|
||||||
update_teletext(sh_video, mpctx->demuxer, 0);
|
update_teletext(sh_video, mpctx->demuxer, 0);
|
||||||
update_osd_msg(mpctx);
|
update_osd_msg(mpctx);
|
||||||
current_module = "decode_video";
|
current_module = "filter video";
|
||||||
#ifdef CONFIG_DVDNAV
|
if (filter_video(sh_video, decoded_frame, sh_video->pts,
|
||||||
decoded_frame = mp_dvdnav_restore_smpi(mpctx, &in_size,&start,
|
mpctx->osd))
|
||||||
decoded_frame);
|
break;
|
||||||
/// 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));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
*blit_frame = 1;
|
||||||
|
return frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double update_video(struct MPContext *mpctx, int *blit_frame)
|
||||||
|
{
|
||||||
|
struct sh_video *sh_video = mpctx->sh_video;
|
||||||
|
double frame_time;
|
||||||
|
*blit_frame = 0;
|
||||||
|
sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ,
|
||||||
|
mpctx->osd); // hack for vf_expand
|
||||||
|
if (!mpctx->opts.correct_pts)
|
||||||
|
return update_video_nocorrect_pts(mpctx, blit_frame);
|
||||||
else {
|
else {
|
||||||
int res = generate_video_frame(mpctx);
|
int res = generate_video_frame(mpctx);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
|
Loading…
Reference in New Issue