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 : {