Mercurial > mplayer.hg
changeset 31972:96559880e475
Improve A/V sync when not using -correct-pts.
This fixes at least playing PAFF streams with the native ts demuxer.
(Breaks the non-standard -demuxer lavf -nocorrect-pts.)
Patch by P«”sztor Szil«”rd, bartosteka freemail hu
author | cehoyos |
---|---|
date | Tue, 07 Sep 2010 16:20:52 +0000 |
parents | 910579aafc61 |
children | c2d29ae022a4 |
files | libmpcodecs/dec_video.c libmpcodecs/dec_video.h mencoder.c mplayer.c |
diffstat | 4 files changed, 51 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpcodecs/dec_video.c Tue Sep 07 16:14:56 2010 +0000 +++ b/libmpcodecs/dec_video.c Tue Sep 07 16:20:52 2010 +0000 @@ -388,7 +388,7 @@ } void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, - int drop_frame, double pts) + int drop_frame, double pts, int *full_frame) { mp_image_t *mpi = NULL; unsigned int t = GetTimer(); @@ -406,6 +406,9 @@ mpi = NULL; } + if (full_frame) + *full_frame = got_picture; + delay = get_current_video_decoder_lag(sh_video); if (correct_pts && pts != MP_NOPTS_VALUE && (got_picture || sh_video->num_buffered_pts < delay)) {
--- a/libmpcodecs/dec_video.h Tue Sep 07 16:14:56 2010 +0000 +++ b/libmpcodecs/dec_video.h Tue Sep 07 16:20:52 2010 +0000 @@ -29,7 +29,7 @@ int init_best_video_codec(sh_video_t *sh_video, char** video_codec_list, char** video_fm_list); void uninit_video(sh_video_t *sh_video); -void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, int drop_frame, double pts); +void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, int drop_frame, double pts, int *full_frame); int filter_video(sh_video_t *sh_video, void *frame, double pts); int get_video_quality_max(sh_video_t *sh_video);
--- a/mencoder.c Tue Sep 07 16:14:56 2010 +0000 +++ b/mencoder.c Tue Sep 07 16:20:52 2010 +0000 @@ -464,7 +464,7 @@ if (vfilter) { int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE); - void *decoded_frame = decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip, MP_NOPTS_VALUE); + void *decoded_frame = decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip, MP_NOPTS_VALUE, NULL); if (decoded_frame) filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE); } @@ -1535,7 +1535,7 @@ (!sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE); void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size, - drop_frame, MP_NOPTS_VALUE); + drop_frame, MP_NOPTS_VALUE, NULL); blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);} if (sh_video->vf_initialized < 0) mencoder_exit(1, NULL);
--- a/mplayer.c Tue Sep 07 16:14:56 2010 +0000 +++ b/mplayer.c Tue Sep 07 16:20:52 2010 +0000 @@ -1827,7 +1827,7 @@ 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); + decoded_frame = decode_video(sh_video, start, in_size, drop_frame, pts, NULL); if (decoded_frame) { update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0); update_teletext(sh_video, mpctx->demuxer, 0); @@ -2381,7 +2381,9 @@ void *decoded_frame = NULL; int drop_frame=0; int in_size; - + int full_frame; + + do { current_module = "video_read_frame"; frame_time = sh_video->next_frame_time; in_size = video_read_frame(sh_video, &sh_video->next_frame_time, @@ -2402,27 +2404,56 @@ 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(frame_time); - update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0); - update_teletext(sh_video, mpctx->demuxer, 0); - update_osd_msg(); current_module = "decode_video"; #ifdef CONFIG_DVDNAV + full_frame = 1; decoded_frame = mp_dvdnav_restore_smpi(&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); + sh_video->pts, &full_frame); + + if (full_frame) { + sh_video->timer += frame_time; + + // Time-based PTS recalculation. + // The key to maintaining A-V sync is to not touch PTS until the proper frame is reached + if (sh_video->pts != MP_NOPTS_VALUE) { + if (sh_video->last_pts != MP_NOPTS_VALUE) { + double pts = sh_video->last_pts + frame_time; + double ptsdiff = fabs(pts - sh_video->pts); + + // Allow starting PTS recalculation at the appropriate frame only + mpctx->framestep_found |= (ptsdiff <= frame_time * 1.5); + + // replace PTS only if we're not too close and not too far + // and a correctly timed frame has been found, otherwise + // keep pts to eliminate rounding errors or catch up with stream + if (ptsdiff > frame_time * 20) + mpctx->framestep_found = 0; + if (ptsdiff * 10 > frame_time && mpctx->framestep_found) + sh_video->pts = pts; + else + mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"Keeping PTS at %6.2f\n", sh_video->pts); + } + sh_video->last_pts = sh_video->pts; + } + if (mpctx->sh_audio) + mpctx->delay -= frame_time; + // video_read_frame can change fps (e.g. for ASF video) + vo_fps = sh_video->fps; + update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0); + update_teletext(sh_video, mpctx->demuxer, 0); + update_osd_msg(); + } #ifdef CONFIG_DVDNAV /// save back last still frame for future display mp_dvdnav_save_smpi(in_size,start,decoded_frame); #endif + } while (!full_frame); + current_module = "filter_video"; *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, sh_video->pts)); @@ -2452,28 +2483,6 @@ frame_time = sh_video->pts - sh_video->last_pts; sh_video->last_pts = sh_video->pts; sh_video->timer += frame_time; - // Time-based PTS recalculation. - // The key to maintaining A-V sync is to not touch PTS until the proper frame is reached - if (sh_video->pts != MP_NOPTS_VALUE) { - if (sh_video->last_pts != MP_NOPTS_VALUE) { - double pts = sh_video->last_pts + frame_time; - double ptsdiff = fabs(pts - sh_video->pts); - - // Allow starting PTS recalculation at the appropriate frame only - mpctx->framestep_found |= (ptsdiff <= frame_time * 1.5); - - // replace PTS only if we're not too close and not too far - // and a correctly timed frame has been found, otherwise - // keep pts to eliminate rounding errors or catch up with stream - if (ptsdiff > frame_time * 20) - mpctx->framestep_found = 0; - if (ptsdiff * 10 > frame_time && mpctx->framestep_found) - sh_video->pts = pts; - else - mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"Keeping PTS at %6.2f\n", sh_video->pts); - } - sh_video->last_pts = sh_video->pts; - } if(mpctx->sh_audio) mpctx->delay -= frame_time; *blit_frame = res > 0; @@ -2662,6 +2671,7 @@ mpctx->num_buffered_frames = 0; mpctx->delay = 0; mpctx->time_frame = 0; + mpctx->framestep_found = 0; // Not all demuxers set d_video->pts during seek, so this value // (which is used by at least vobsub and edl code below) may // be completely wrong (probably 0). @@ -3711,6 +3721,7 @@ int frame_time_remaining=0; // flag int blit_frame=0; mpctx->num_buffered_frames=0; +mpctx->framestep_found=0; // Make sure old OSD does not stay around, // e.g. with -fixed-vo and same-resolution files