Mercurial > mplayer.hg
changeset 18710:c528c6c518f1
Clean up audio pts handling, make audio pts tracking in the audio-only
case work the same as with video.
author | uau |
---|---|
date | Wed, 14 Jun 2006 19:48:54 +0000 |
parents | 7ca8f5ab5136 |
children | 4d87a5c4611c |
files | libmpdemux/demux_aac.c libmpdemux/demux_asf.c libmpdemux/demux_audio.c libmpdemux/demux_demuxers.c libmpdemux/demux_mov.c libmpdemux/demux_mpc.c libmpdemux/demux_ogg.c libmpdemux/demux_rawaudio.c libmpdemux/demux_xmms.c mplayer.c |
diffstat | 10 files changed, 68 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/demux_aac.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_aac.c Wed Jun 14 19:48:54 2006 +0000 @@ -248,7 +248,6 @@ nf -= num; } } - sh_audio->delay = priv->last_pts - (ds_tell_pts(demuxer->audio)-sh_audio->a_in_buffer_len)/(float)priv->bitrate; }
--- a/libmpdemux/demux_asf.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_asf.c Wed Jun 14 19:48:54 2006 +0000 @@ -493,9 +493,7 @@ ds_fill_buffer(d_audio); } - if (d_video->id < 0) - sh_audio->delay = d_audio->pts; - else + if (d_video->id >= 0) while(1){ if(sh_audio && !d_audio->eof){ float a_pts=d_audio->pts;
--- a/libmpdemux/demux_audio.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_audio.c Wed Jun 14 19:48:54 2006 +0000 @@ -620,8 +620,7 @@ } resize_demux_packet(dp, l); - ds->pts = priv->last_pts - (ds_tell_pts(demux->audio) - - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + dp->pts = priv->last_pts; ds_add_packet(ds, dp); return 1; } @@ -667,7 +666,6 @@ } if(len > 0) high_res_mp3_seek(demuxer,len); - sh_audio->delay = priv->last_pts - (ds_tell_pts(demuxer->audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; return; } @@ -679,13 +677,10 @@ if(demuxer->movi_end && pos >= demuxer->movi_end) { pos = demuxer->movi_end; - //sh_audio->delay = (stream_tell(s) - demuxer->movi_start)/(float)sh_audio->i_bps; - //return; } else if(pos < demuxer->movi_start) pos = demuxer->movi_start; priv->last_pts = (pos-demuxer->movi_start)/(float)sh_audio->i_bps; - sh_audio->delay = priv->last_pts - (ds_tell_pts(demuxer->audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; switch(priv->frmt) { case WAV:
--- a/libmpdemux/demux_demuxers.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_demuxers.c Wed Jun 14 19:48:54 2006 +0000 @@ -78,7 +78,6 @@ // In case the demuxer don't set pts if(!demuxer->audio->pts) demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps); - sh->delay = 0; } if(priv->sd != priv->vd)
--- a/libmpdemux/demux_mov.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_mov.c Wed Jun 14 19:48:54 2006 +0000 @@ -2123,8 +2123,6 @@ //if(!(flags&1)) pts+=ds->pts; ds->pts=mov_seek_track(trak,pts,flags); if (ds->pts < 0) ds->eof = 1; - if (demuxer->video->id < 0) - ((sh_audio_t*)ds->sh)->delay = ds->pts; } }
--- a/libmpdemux/demux_mpc.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_mpc.c Wed Jun 14 19:48:54 2006 +0000 @@ -145,8 +145,7 @@ priv->last_pts = 0; else priv->last_pts += priv->pts_per_packet; - ds->pts = priv->last_pts - (ds_tell_pts(demux->audio) - - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + dp->pts = priv->last_pts; ds_add_packet(ds, dp); return 1; } @@ -177,8 +176,6 @@ if (s->eof) break; } if (!sh_audio) return; - sh_audio->delay = priv->last_pts - (ds_tell_pts(demuxer->audio) - - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; } static void demux_close_mpc(demuxer_t* demuxer) {
--- a/libmpdemux/demux_ogg.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_ogg.c Wed Jun 14 19:48:54 2006 +0000 @@ -1599,8 +1599,6 @@ vo_osd_changed(OSDTYPE_SUBTITLE); clear_sub = -1; demux_ogg_add_packet(ds,os,ds->id,&op); - if (demuxer->video->id < 0) - sh_audio->delay = pts; return; } }
--- a/libmpdemux/demux_rawaudio.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_rawaudio.c Wed Jun 14 19:48:54 2006 +0000 @@ -92,7 +92,6 @@ pos -= (pos % (sh_audio->channels * sh_audio->samplesize) ); stream_seek(s,pos); - sh_audio->delay= (pos-ds_tell_pts(demuxer->audio)-sh_audio->a_in_buffer_len) / (float)(sh_audio->wf->nAvgBytesPerSec); // printf("demux_rawaudio: streamtell=%d\n",(int)stream_tell(demuxer->stream)); }
--- a/libmpdemux/demux_xmms.c Wed Jun 14 16:08:49 2006 +0000 +++ b/libmpdemux/demux_xmms.c Wed Jun 14 19:48:54 2006 +0000 @@ -287,7 +287,7 @@ pthread_mutex_lock(&xmms_mutex); dp = new_demux_packet(XMMS_PACKETSIZE/2); - ds->pts = priv->spos / sh_audio->wf->nAvgBytesPerSec; + dp->pts = priv->spos / sh_audio->wf->nAvgBytesPerSec; ds->pos = priv->spos; memcpy(dp->buffer,xmms_audiobuffer,XMMS_PACKETSIZE/2); @@ -319,7 +319,6 @@ priv->ip->seek((pos<0)?0:pos); priv->spos=pos * sh_audio->wf->nAvgBytesPerSec; - sh_audio->delay=pos; //priv->spos / sh_audio->wf->nAvgBytesPerSec; } static void demux_close_xmms(demuxer_t* demuxer) {
--- a/mplayer.c Wed Jun 14 16:08:49 2006 +0000 +++ b/mplayer.c Wed Jun 14 19:48:54 2006 +0000 @@ -2415,6 +2415,58 @@ ///@} // Command2Property + +// Return pts value corresponding to the end point of audio written to the +// ao so far. +static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio) +{ + // first calculate the end pts of audio that has been output by decoder + double a_pts = sh_audio->pts; + if (a_pts != MP_NOPTS_VALUE) + // Good, decoder supports new way of calculating audio pts. + // sh_audio->pts is the timestamp of the latest input packet with + // known pts that the decoder has decoded. sh_audio->pts_bytes is + // the amount of bytes the decoder has written after that timestamp. + a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps; + else { + // Decoder doesn't support new way of calculating pts (or we're + // being called before it has decoded anything with known timestamp). + // Use the old method of audio pts calculation: take the timestamp + // of last packet with known pts the decoder has read data from, + // and add amount of bytes read after the beginning of that packet + // divided by input bps. This will be inaccurate if the input/output + // ratio is not constant for every audio packet or if it is constant + // but not accurately known in sh_audio->i_bps. + + a_pts = d_audio->pts; + // ds_tell_pts returns gets bytes read after last timestamp from + // demuxing layer, decoder might use sh_audio->a_in_buffer for bytes + // it has read but not decoded + a_pts += (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len) / + (double)sh_audio->i_bps; + } + // Now a_pts hopefully holds the pts for end of audio from decoder. + // Substract data in buffers between decoder and audio out. + + // Decoded but not filtered + a_pts -= sh_audio->a_buffer_len / (double)sh_audio->o_bps; + + // Data that was ready for ao but was buffered because ao didn't fully + // accept everything to internal buffers yet + a_pts -= sh_audio->a_out_buffer_len * playback_speed / (double)ao_data.bps; + + return a_pts; +} + +// Return pts value corresponding to currently playing audio. +static double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, + ao_functions_t *audio_out) +{ + return written_audio_pts(sh_audio, d_audio) - playback_speed * + audio_out->get_delay(); +} + + int main(int argc,char* argv[]){ @@ -3539,7 +3591,6 @@ int too_slow_frame_cnt=0; int too_fast_frame_cnt=0; // for auto-quality: -float AV_delay=0; // average of A-V timestamp differences double vdecode_time; unsigned int lastframeout_ts=0; /*float time_frame_corr_avg=0;*/ /* unused */ @@ -3678,7 +3729,7 @@ if(!sh_video) { // handle audio-only case: if(!quiet) { - float a_pos = sh_audio->delay - audio_out->get_delay() * playback_speed; + double a_pos = playing_audio_pts(sh_audio, d_audio, audio_out); print_status(a_pos, 0, 0); } if(d_audio->eof && sh_audio->a_in_buffer_len <= 0 && sh_audio->a_buffer_len <= 0) eof = PT_NEXT_ENTRY; @@ -3923,13 +3974,9 @@ current_module="av_sync"; if(sh_audio){ - double a_pts=0; - double v_pts=0; - - // unplayed bytes in our and soundcard/dma buffer: - float delay=playback_speed*audio_out->get_delay()+(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps; - - if (autosync){ + double a_pts, v_pts; + + if (autosync) /* * If autosync is enabled, the value for delay must be calculated * a bit differently. It is set only to the difference between @@ -3941,31 +3988,16 @@ * value here, even a "corrected" one, would be incompatible with * autosync mode.) */ - delay=sh_audio->delay; - delay+=(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps; - } - delay += sh_audio->a_out_buffer_len*playback_speed/(float)ao_data.bps; - - { - // PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec) - a_pts = sh_audio->pts; - if (a_pts == MP_NOPTS_VALUE) { - // Decoder doesn't support tracking timestamps or demuxer doesn't - // set them properly in individual packets, use old inaccurate method - a_pts=d_audio->pts; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - } - else - a_pts += sh_audio->pts_bytes / (float)sh_audio->o_bps; - } + a_pts = written_audio_pts(sh_audio, d_audio) - sh_audio->delay; + else + a_pts = playing_audio_pts(sh_audio, d_audio, audio_out); + v_pts=sh_video ? sh_video->pts : d_video->pts; - mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"### A:%8.3f (%8.3f) V:%8.3f A-V:%7.4f \n",a_pts,a_pts-audio_delay-delay,v_pts,(a_pts-delay-audio_delay)-v_pts); - { static int drop_message=0; - float x; - AV_delay=(a_pts-delay-audio_delay)-v_pts; + double AV_delay = a_pts - audio_delay - v_pts; + double x; if(AV_delay>0.5 && drop_frame_cnt>50 && drop_message==0){ ++drop_message; mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow); @@ -3985,7 +4017,7 @@ max_pts_correction=sh_video->frametime*0.10; // +-10% of time if(!frame_time_remaining){ sh_audio->delay+=x; c_total+=x;} // correction if(!quiet) - print_status(a_pts - audio_delay - delay, AV_delay, c_total); + print_status(a_pts - audio_delay, AV_delay, c_total); } } else { @@ -4570,7 +4602,7 @@ pos = sh_video->pts; else if (sh_audio && audio_out) - pos = sh_audio->delay - audio_out->get_delay() * playback_speed; + pos = playing_audio_pts(sh_audio, d_audio, audio_out); mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_TIME_POSITION=%.1f\n", pos); } break; case MP_CMD_SWITCH_AUDIO : {