From e2727ec797e19fb6d4d2d3338ce17dce976e0b28 Mon Sep 17 00:00:00 2001 From: uau Date: Thu, 6 Jul 2006 06:58:17 +0000 Subject: Add a new video pts tracking mode, enabled by option -correct-pts. This mode has the following differences: - Video timing is correct for streams with B frames, at least with some demuxers. - Video filters can modify frame timestamps and insert new frames, and removing frames is handled better than before. - Some things are known to break, it's not usable as the default yet. Things should work as before when the -correct-pts option is not used. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@18922 b3059339-0415-0410-9bf9-f77b7e298cf2 --- mplayer.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'mplayer.c') diff --git a/mplayer.c b/mplayer.c index b78b5692f3..7c92624cb6 100644 --- a/mplayer.c +++ b/mplayer.c @@ -2466,6 +2466,40 @@ static double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, } +static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video) +{ + unsigned char *start; + int in_size; + int hit_eof=0; + double pts; + + while (1) { + current_module = "decode video"; + // XXX Time used in this call is not counted in any performance + // timer now + 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; + if (pts == MP_NOPTS_VALUE) + mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts value from demuxer MISSING\n"); + if (decode_video(sh_video, start, in_size, 0, pts)) + break; + if (hit_eof) + return 0; + } + return 1; +} + + int main(int argc,char* argv[]){ @@ -3505,9 +3539,11 @@ sh_video->video_out=video_out; inited_flags|=INITED_VO; } +struct {double pts; vo_functions_t *vo;} vf_vo_data; +vf_vo_data.vo = video_out; current_module="init_video_filters"; { - char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL }; + char* vf_arg[] = { "_oldargs_", (char*)&vf_vo_data , NULL }; sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg); } #ifdef HAVE_MENU @@ -3594,6 +3630,7 @@ fflush(stdout); //float v_frame=0; // Video float time_frame=0; // Timer //float num_frames=0; // number of frames played +double last_pts = MP_NOPTS_VALUE; int grab_frames=0; int drop_frame=0; // current dropping status int dropped_frames=0; // how many frames dropped since last non-dropped frame @@ -3768,7 +3805,7 @@ if(!sh_video) { //-------------------- Decode a frame: ----------------------- blit_frame = 0; // Don't blit if we hit EOF vdecode_time=video_time_usage; - while(1) + if (!correct_pts) while(1) { unsigned char* start=NULL; int in_size; // get it! @@ -3803,6 +3840,32 @@ if(!sh_video) { blit_frame=decode_video(sh_video,start,in_size,drop_frame, MP_NOPTS_VALUE); break; } + else while (1) { + if (!generate_video_frame(sh_video, d_video)) { + eof = 1; + break; + } + sh_video->pts = vf_vo_data.pts; + if (sh_video->pts == MP_NOPTS_VALUE) { + mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts after filters MISSING\n"); + sh_video->pts == last_pts; + } + if (last_pts == MP_NOPTS_VALUE) + last_pts = sh_video->pts; + else if (last_pts >= sh_video->pts) { + last_pts = sh_video->pts; + mp_msg(MSGT_CPLAYER, MSGL_WARN, "pts value <= previous"); + } + frame_time = sh_video->pts - last_pts; + last_pts = sh_video->pts; + sh_video->timer += frame_time; + time_frame += frame_time; // for nosound + if(sh_audio) + sh_audio->delay -= frame_time; + blit_frame = 1; + break; + } + vdecode_time=video_time_usage-vdecode_time; //------------------------ frame decoded. -------------------- @@ -4728,6 +4791,8 @@ if(rel_seek_secs || abs_seek_pos){ current_module="seek_video_reset"; resync_video_stream(sh_video); if(vo_config_count) video_out->control(VOCTRL_RESET,NULL); + sh_video->num_buffered_pts = 0; + last_pts = MP_NOPTS_VALUE; } if(sh_audio){ -- cgit v1.2.3