summaryrefslogtreecommitdiffstats
path: root/mplayer.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-01-15 00:32:03 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-01-15 00:32:03 +0200
commit2d532689fcc96deaa8ae8c05c34e315cfcef8350 (patch)
tree22fb44c6714c0f34616666c03910733a619b052a /mplayer.c
parent02bc48b67dd88c974c8f9298a0c50cbfcd51af41 (diff)
downloadmpv-2d532689fcc96deaa8ae8c05c34e315cfcef8350.tar.bz2
mpv-2d532689fcc96deaa8ae8c05c34e315cfcef8350.tar.xz
core: Improve handling of bad timestamps
Rewrite some of the -correct-pts frame generation code. The most noticeable difference is that video timestamps which jump around but do not go backwards more than 0.5 seconds will not affect overall video playback speed. Only larger jumps are treated as timestamp resets and increase the overall length of the video timeline. This will hopefully give watchable results for videos which have broken timestamps or which MPlayer does not demux or otherwise handle properly.
Diffstat (limited to 'mplayer.c')
-rw-r--r--mplayer.c132
1 files changed, 64 insertions, 68 deletions
diff --git a/mplayer.c b/mplayer.c
index 2ece0607ef..5d16cd9e57 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -1716,51 +1716,6 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time) {
return 0;
}
-static int generate_video_frame(struct MPContext *mpctx)
-{
- sh_video_t * const sh_video = mpctx->sh_video;
- demux_stream_t *d_video = mpctx->d_video;
-
- unsigned char *start;
- int in_size;
- int hit_eof=0;
- double pts;
-
- while (1) {
- int drop_frame = check_framedrop(mpctx, sh_video->frametime);
- void *decoded_frame;
- current_module = "decode video";
- // XXX Time used in this call is not counted in any performance
- // timer now, OSD is not updated correctly for filter-added frames
- if (vf_output_queued_frame(sh_video->vfilter))
- break;
- current_module = "video_read_frame";
- in_size = ds_get_packet_pts(d_video, &start, &pts);
- if (in_size < 0) {
- // try to extract last frames in case of decoder lag
- in_size = 0;
- pts = 1e300;
- hit_eof = 1;
- }
- if (in_size > max_framesize)
- max_framesize = in_size;
- current_module = "decode video";
- decoded_frame = decode_video(sh_video, start, in_size, drop_frame, pts);
- if (decoded_frame) {
- 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;
- } else if (drop_frame)
- return -1;
- if (hit_eof)
- return 0;
- }
- return 1;
-}
#ifdef HAVE_RTC
int rtc_fd = -1;
@@ -2280,35 +2235,76 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx,
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 {
- int res = generate_video_frame(mpctx);
- if (!res)
- return -1;
- sh_video->vfilter->control(sh_video->vfilter, VFCTRL_GET_PTS,
- &sh_video->pts);
- if (sh_video->pts == MP_NOPTS_VALUE) {
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts after filters MISSING\n");
- sh_video->pts = sh_video->last_pts;
- }
- if (sh_video->last_pts == MP_NOPTS_VALUE)
- sh_video->last_pts= sh_video->pts;
- else if (sh_video->last_pts >= sh_video->pts) {
- sh_video->last_pts = sh_video->pts;
- mp_msg(MSGT_CPLAYER, MSGL_INFO, "pts value <= previous\n");
- }
- frame_time = sh_video->pts - sh_video->last_pts;
- sh_video->last_pts = sh_video->pts;
- sh_video->timer += frame_time;
- if(mpctx->sh_audio)
- mpctx->delay -= frame_time;
- *blit_frame = res > 0;
+
+ double pts;
+
+ while (1) {
+ current_module = "filter_video";
+ // XXX Time used in this call is not counted in any performance
+ // timer now, OSD time is not updated correctly for filter-added frames
+ if (vf_output_queued_frame(sh_video->vfilter))
+ break;
+ unsigned char *packet = NULL;
+ bool hit_eof = false;
+ int in_size = ds_get_packet_pts(mpctx->d_video, &packet, &pts);
+ if (in_size < 0) {
+ // try to extract last frames in case of decoder lag
+ in_size = 0;
+ pts = 1e300;
+ hit_eof = true;
+ }
+ if (in_size > max_framesize)
+ max_framesize = in_size;
+ current_module = "decode video";
+ int framedrop_type = check_framedrop(mpctx, sh_video->frametime);
+ void *decoded_frame = decode_video(sh_video, packet, in_size,
+ framedrop_type, pts);
+ 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;
+ } else if (hit_eof)
+ return -1;
}
+
+ sh_video->vfilter->control(sh_video->vfilter, VFCTRL_GET_PTS, &pts);
+ if (pts == MP_NOPTS_VALUE) {
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, "Video pts after filters MISSING\n");
+ // Try to use decoder pts from before filters
+ pts = sh_video->pts;
+ }
+ sh_video->pts = pts;
+ if (sh_video->last_pts == MP_NOPTS_VALUE)
+ sh_video->last_pts = sh_video->pts;
+ else if (sh_video->last_pts >= sh_video->pts) {
+ mp_msg(MSGT_CPLAYER, MSGL_INFO, "Non-increasing video pts: %f <= %f\n",
+ sh_video->pts, sh_video->last_pts);
+ /* If the difference in pts is small treat it as jitter around the
+ * right value (possibly caused by incorrect timestamp ordering) and
+ * just show this frame immediately after the last one.
+ * Treat bigger differences as timestamp resets and start counting
+ * timing of later frames from the position of this one. */
+ if (sh_video->last_pts - sh_video->pts > 0.5)
+ sh_video->last_pts = sh_video->pts;
+ else
+ sh_video->pts = sh_video->last_pts;
+ }
+ double frame_time = sh_video->pts - sh_video->last_pts;
+ sh_video->last_pts = sh_video->pts;
+ sh_video->timer += frame_time;
+ if (mpctx->sh_audio)
+ mpctx->delay -= frame_time;
+ *blit_frame = 1;
return frame_time;
}